Subversion Repositories HomeAutomation

Rev

Rev 638 | Rev 731 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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