Subversion Repositories HomeAutomation

Rev

Go to most recent revision | Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
638 eqlazer 1
/*
2
 * AntennaControl
3
 *
4
 * Build for use at ETA, http://www.eta.chalmers.se/, controlling their 2 meter quad antenna.
5
 *
6
 * @date 2007-09-22
7
 * @author Erik Larsson
8
 *
9
 */
10
 
11
#include <inttypes.h>
12
#include <avr/interrupt.h>
13
#include <stdio.h>
14
#include <string.h>
15
#include <avr/eeprom.h>
16
#include <config.h> // All configuration parameters
17
#include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
18
//#include <drivers/uart/serial.h>
19
#include <drivers/timer/timer.h>
20
 
21
#define APP_TYPE    0xf0a0
22
#define APP_VERSION 0x0001
23
 
24
#define AZIMUTH 0
25
#define ELEVATION 1
26
 
27
#define ROTATE_STOP 0
28
#define ROTATE_PLUS 1
29
#define ROTATE_MINUS 2
30
 
31
#define SET 0
32
#define GET 1
33
#define CALIBRATE_ELEVATION 0
34
#define CALIBRATE_AZIMUTH 2
35
 
36
// Make sure this is a power of 2
37
#define AVERAGE_SIZE 16
38
#define AVERAGE_SIZE_SHIFT 4
39
 
40
// Essential pins
41
// 0: PD2 azimuth plus
42
// 1: PD1 azimuth minus
43
// 2: PD0 elevation plus
44
// 3: PD4 elevation minus
45
// 8: PC4 ADC4 azimuth feedback
46
// 9: PC5 ADC5 elevation feedback
47
 
48
 
49
 
50
// A simple message "queue", with space for one message only.
51
// These are declared volatile to tell the compiler not to optimize away accesses.
52
volatile Can_Message_t rxMsg; // Message storage
53
volatile uint8_t rxMsgFull;   // Synchronization flag
54
 
55
//uint16_t actualElevationValue;
56
//uint16_t desiredElevationValue;
57
//uint16_t actualAzimuthValue;
58
//uint16_t desiredAzimuthValue;
59
 
60
uint16_t azimuthReadout[ AVERAGE_SIZE ];
61
uint16_t elevationReadout[ AVERAGE_SIZE ];
62
 
63
// CAN message reception callback.
64
// This function runs with interrupts disabled, keep it as short as possible.
65
void can_receive( Can_Message_t *msg ) {
66
    if (!rxMsgFull) {
67
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
68
        rxMsgFull = 1;
69
    }
70
}
71
 
72
// Calibration function
73
// axis: Elevation / Azimuth
74
// mode: set / get
75
// value:
76
int16_t calibration( uint8_t axis, uint8_t mode, uint16_t value );
77
 
78
// Turn rotors
79
// axis: Elevation / Azimuth
80
// position: 0-1024
81
uint8_t turn( uint8_t axis, uint16_t position );
82
 
83
// Get position
84
// axis: Elevation / Azimuth
85
// Gets the average value for compensation of distorsions
86
uint16_t getPosition( uint8_t axis );
87
 
88
// Read position
89
// axis: Elevation / Azimuth
90
// uses two adc
91
uint16_t readPosition(uint8_t axis);
92
 
93
void changeFeedbackAxis( uint8_t axis );
94
 
95
// Initiate ADC
96
void initAdcFeedback( void );
97
 
98
// Store result from ADC
99
void readAdcFeedback( void );
100
 
101
// Control rotation relays
102
// axis: Elevation / Azimuth
103
void controlRelay( uint8_t axis, uint8_t direction );
104
 
105
// Timer callback function used for some timer tests
106
void timer_callback( uint8_t timer ) {
107
    Can_Message_t msg;
108
 
109
    msg.ExtendedFlag = 1;
110
    msg.Id = (CAN_TST << CAN_SHIFT_CLASS) | NODE_ID;
111
    msg.RemoteFlag = 0;
112
    msg.DataLength = 1;
113
    msg.Data.bytes[0] = timer;
114
 
115
    BIOS_CanSend(&msg);
116
}
117
 
118
 
119
ISR( ADC_vect ) // ADC Conversion Complete
120
{
121
 
122
}
123
 
124
int main( void )
125
{
126
    // Enable interrupts as early as possible
127
    sei();
128
 
129
    Timer_Init();
130
//  Serial_Init();
131
 
132
//  unsigned long time;
133
 
134
    Can_Message_t txMsg;
135
    txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
136
    txMsg.DataLength = 4;
137
    txMsg.RemoteFlag = 0;
138
    txMsg.ExtendedFlag = 1;
139
    txMsg.Data.words[0] = APP_TYPE;
140
    txMsg.Data.words[1] = APP_VERSION;
141
 
142
    // Set up callback for CAN reception, this is optional if only sending is required.
143
    BIOS_CanCallback = &can_receive;
144
    // Send CAN_NMT_APP_START
145
    BIOS_CanSend(&txMsg);
146
 
147
    printf("AVR Test Application\n");
148
 
149
    txMsg.Id = (CAN_TST << CAN_SHIFT_CLASS) | NODE_ID;
150
//  txMsg.Data.dwords[0] = 0x01020304;
151
//  txMsg.DataLength = 8;
152
 
153
    // Set up three timers (assume at least three has been defined)
154
    // The timeout is specified in ticks, which is equal to ms if
155
    // the tick frequency is set to 1000.
156
    Timer_SetTimeout(0, 10, TimerTypeFreeRunning, 0);
157
//  Timer_SetTimeout(1, 10768, TimerTypeOneShot, &timer_callback);
158
//  Timer_SetTimeout(2, 3141, TimerTypeFreeRunning, &timer_callback);
159
 
160
    while (1) {
161
        if (Timer_Expired(0)) {
162
//          ad-omvandla
163
        }
164
 
165
        if (rxMsgFull) {
166
//          // Print the received message
167
//          printf("RX: ID=%08lx, DLC=%u, EXT=%u, RTR=%u, data={ ", 
168
//                  rxMsg.Id,
169
//                  (uint16_t)rxMsg.DataLength, 
170
//                  (uint16_t)rxMsg.ExtendedFlag, 
171
//                  (uint16_t)rxMsg.RemoteFlag);
172
//          for (uint8_t i=0; i<rxMsg.DataLength; i++) {
173
//              printf("%02x ", rxMsg.Data.bytes[i]);
174
//          }
175
//          printf("}\n");
176
 
177
 
178
            rxMsgFull = 0; //  
179
        }
180
    }
181
 
182
    return 0;
183
}
184
 
185
 
186
int16_t calibration( uint8_t axis, uint8_t mode, uint16_t value )
187
{
188
    // set / get calibration value
189
    if( SET == mode ){
190
        if( ELEVATION == axis ){
191
            eeprom_write_word( CALIBRATE_ELEVATION, value );
192
        }else if( AZIMUTH == axis ){
193
            eeprom_write_word( CALIBRATE_AZIMUTH, value );
194
        }  
195
    }else if( GET == mode ){
196
        if( ELEVATION == axis ){
197
            return eeprom_read_word( CALIBRATE_ELEVATION );
198
        }else if( AZIMUTH == axis ){
199
            return eeprom_read_word( CALIBRATE_AZIMUTH );
200
        }      
201
    }
202
    return 0;
203
}
204
 
205
uint8_t turn( uint8_t axis, uint16_t position )
206
{
207
    // start relay
208
    // read feedback
209
    // callibrate measurement
210
 
211
    while(0){
212
 
213
    }
214
    return 0;
215
}
216
 
217
uint16_t getPosition( uint8_t axis )
218
{
219
/*  uint16_t position = 0;
220
 
221
    // Get average value of position
222
    for( uint8_t i ; i < 4 ; i++ ){
223
        position += readPosition( axis );
224
    }
225
 
226
    position = (position >> 2);
227
 
228
    return position;
229
*/
230
    return 0;
231
}
232
 
233
uint16_t readPosition( uint8_t axis )
234
{
235
    uint16_t averageValue = 0;
236
    uint16_t *measuredAxis;
237
 
238
    if( ELEVATION == axis ){
239
        // Calculate elevation value
240
        measuredAxis = elevationReadout;
241
    }else if( AZIMUTH == axis ){
242
        // Calculate aximuth value
243
        measuredAxis = azimuthReadout;
244
    }else{
245
        return 0;
246
    }
247
 
248
    for(uint8_t i = 0 ; i<AVERAGE_SIZE ; i++ ){
249
        // Summarize
250
        averageValue += measuredAxis[i];
251
    }
252
 
253
    averageValue = averageValue >> AVERAGE_SIZE_SHIFT;
254
 
255
 
256
 
257
    return averageValue;
258
}
259
 
260
 
261
void changeFeedbackAxis( uint8_t axis )
262
{
263
    if( AZIMUTH == axis ){
264
        // Enable ADC4
265
        ADMUX |= ( 1 << MUX2 );
266
        ADMUX &= ~(( 1 << MUX0 )|( 1 << MUX1 )|( 1 << MUX3 ));
267
    }else if( ELEVATION == axis ){
268
        // Enable ADC5
269
        ADMUX |= ( 1 << MUX0 )|( 1 << MUX2 );
270
        ADMUX &= ~(( 1 << MUX1 )|( 1 << MUX3 ));
271
    }  
272
}
273
 
274
void initAdcFeedback( void )
275
{
276
    // ADC4: Azimuth feedback
277
    // ADC5: Elevation feedback
278
 
279
    // Enable ADC4
280
    ADMUX |= ( 1 << MUX2 );
281
    ADMUX &= ~(( 1 << MUX0 )|( 1 << MUX1 )|( 1 << MUX3 ));
282
 
283
    // Prescaler /128
284
    ADCSRA |= ( 1 << ADPS2)|( 1 << ADPS1)|( 1 << ADPS0);
285
 
286
    // Enable AVcc as Voltage Reference
287
    ADMUX |= ( 1 << REFS0 );
288
    ADMUX &= ~( 1 << REFS1 );
289
 
290
    // Right adjust the result
291
    ADMUX &= ~( 1 << ADLAR );
292
 
293
    // Auto Trigger
294
//  ADCSRA |= ( 1 << ADATE );
295
 
296
    // Disable digital input
297
    DIDR0 |= ( 1 << ADC5D )|( 1 << ADC4D );
298
 
299
    // Wake uo ADC and enable it
300
    PRR &= ~( 1 << PRADC );
301
    ADCSRA |= ( 1 << ADEN );
302
}
303
 
304
void controlRelay( uint8_t axis, uint8_t direction )
305
{
306
    if( AZIMUTH == axis ){
307
 
308
        if( ROTATE_PLUS == direction ){
309
            PORTD &= ~(1 << PD2);
310
            PORTD |= (1 << PD1);
311
        }else if ( ROTATE_MINUS == direction ){
312
            PORTD &= ~(1 << PD1);
313
            PORTD |= (1 << PD2);
314
        }else{
315
            // stop azimuth rotor
316
            PORTD |= (1 << PD1);
317
            PORTD |= (1 << PD2);
318
        }
319
 
320
    }else if( ELEVATION == axis ){
321
 
322
        if( ROTATE_PLUS == direction ){
323
            PORTD &= ~(1 << PD0);
324
            PORTD |= (1 << PD4);
325
        }else if ( ROTATE_MINUS == direction ){
326
            PORTD &= ~(1 << PD4);
327
            PORTD |= (1 << PD0);
328
        }else{
329
            // stop elevation rotor
330
            PORTD |= (1 << PD0);
331
            PORTD |= (1 << PD4);
332
        }
333
 
334
    }else{
335
        // stop all rotors
336
        PORTD |= (1 << PD0);
337
        PORTD |= (1 << PD1);
338
        PORTD |= (1 << PD2);
339
        PORTD |= (1 << PD4);
340
    }
341
 
342
}
343
 
344
void readAdcFeedback( void )
345
{
346
    static uint8_t azimuthArrayPosition = 0;
347
    static uint8_t elevationArrayPosition = 0;
348
    static uint8_t lastAxis = AZIMUTH;
349
 
350
    while( ADCSRA & (1 << ADSC) ); // Wait for conversion to be done
351
 
352
    // Get measurement
353
    if( AZIMUTH == lastAxis ){
354
        azimuthReadout[ azimuthArrayPosition ] = ADCW;
355
        azimuthArrayPosition++;
356
        if( AVERAGE_SIZE <= azimuthArrayPosition ){
357
            azimuthArrayPosition = 0;
358
        }
359
 
360
        lastAxis = ELEVATION;
361
 
362
    }else if( ELEVATION == lastAxis ){
363
        elevationReadout[ elevationArrayPosition ] = ADCW;
364
        elevationArrayPosition++;
365
        if( AVERAGE_SIZE <= elevationArrayPosition ){
366
            elevationArrayPosition = 0;
367
        }
368
 
369
        lastAxis = AZIMUTH;
370
    }
371
 
372
    // Next time read other axis
373
    changeFeedbackAxis( lastAxis );
374
 
375
    // Start next measurement
376
    ADCSRA |= (1 << ADSC);
377
}