Subversion Repositories HomeAutomation

Rev

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

Rev 682 Rev 731
Line 2... Line 2...
2
 * AntennaControl
2
 * AntennaControl
3
 *
3
 *
4
 * Build for use at ETA, http://www.eta.chalmers.se/, controlling their 2 meter yagi antenna.
4
 * Build for use at ETA, http://www.eta.chalmers.se/
-
 
5
 * controlling their 2 meter yagi antenna.
-
 
6
 * For the moment only support for azimuth,
-
 
7
 * elevation is yet to be implemented.
5
 *
8
 *
6
 * @date 2007-10-28
9
 * @date 2007-12-10
7
 * @author Erik Larsson
10
 * @author Erik Larsson
8
 *
11
 *
9
 */
12
 */
10
 
13
 
-
 
14
/*
-
 
15
 * This version uses a NodeEssential
-
 
16
 * and the pins used are:
-
 
17
 * 0: PD2 azimuth plus
-
 
18
 * 1: PD1 azimuth minus
-
 
19
 * 8: PC4 ADC4 azimuth feedback
-
 
20
 */
-
 
21
 
-
 
22
/*-----------------------------------------------------------------------------
-
 
23
 * Includes
-
 
24
 *---------------------------------------------------------------------------*/
11
#include <inttypes.h>
25
#include <inttypes.h>
12
#include <avr/interrupt.h>
26
#include <avr/interrupt.h>
13
#include <stdio.h>
27
#include <stdio.h>
14
#include <string.h>
28
#include <string.h>
15
#include <avr/eeprom.h>
29
#include <avr/eeprom.h>
16
#include <config.h> // All configuration parameters
30
#include <config.h> // All configuration parameters
17
#include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
31
#include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
18
#include <drivers/timer/timer.h>
32
#include <drivers/timer/timer.h>
19
 
33
 
-
 
34
/*-----------------------------------------------------------------------------
-
 
35
 * Defines
-
 
36
 *---------------------------------------------------------------------------*/
20
#define APP_TYPE    0xf0a0
37
#define APP_TYPE    0xf0a0
21
#define APP_VERSION 0x0001
38
#define APP_VERSION 0x0002
22
 
39
 
23
#define AZIMUTH 0
40
#define AZIMUTH 0
24
 
41
 
25
#define ROTATE_STOP 0
42
#define ROTATE_STOP 0
26
#define ROTATE_PLUS 1
43
#define ROTATE_PLUS 1
Line 28... Line 45...
28
 
45
 
29
#define SET 0
46
#define SET 0
30
#define GET 1
47
#define GET 1
31
 
48
 
32
#define CALIBRATE_AZIMUTH 0 // EEPROM adress
49
#define CALIBRATE_AZIMUTH 0 // EEPROM adress
33
 
50
 
34
// Make sure this is a power of 2
51
// Make sure this is a power of 2
35
#define AVERAGE_SIZE 16
52
#define AVERAGE_SIZE 16
36
#define AVERAGE_SIZE_SHIFT 4
53
#define AVERAGE_SIZE_SHIFT 4
37
 
54
 
38
// Tillfälliga defines
55
//FIXME move these message id defines
39
#define MSG_CAL_SET 0x0100001UL
56
#define MSG_CAL_SET 0x11100001UL
40
#define MSG_CAL_GET 0x0100002UL
57
#define MSG_CAL_GET 0x11100002UL
41
#define MSG_ABS 0x01000031UL
58
#define MSG_ABS 0x111000031UL
42
#define MSG_REL 0x0100004UL
59
#define MSG_REL 0x11100004UL
43
#define MSG_START 0x0100005UL
60
#define MSG_START 0x11100005UL
44
#define MSG_STOP 0x0100006UL
61
#define MSG_STOP 0x11100006UL
45
#define MSG_STATUS 0x0100007UL
62
#define MSG_STATUS 0x11100007UL
46
 
-
 
47
 
-
 
48
// ----------
-
 
49
 
-
 
50
// Essential pins
-
 
51
// 0: PD2 azimuth plus
-
 
52
// 1: PD1 azimuth minus 
-
 
53
// 8: PC4 ADC4 azimuth feedback
63
#define MSG_CAL_RET 0x111000f2UL
54
 
-
 
55
 
64
 
56
 
65
 
57
// A simple message "queue", with space for one message only.
66
// A simple message "queue", with space for one message only.
58
// These are declared volatile to tell the compiler not to optimize away accesses.
67
// These are declared volatile to tell the compiler not to optimize away accesses.
59
volatile Can_Message_t rxMsg; // Message storage
68
volatile Can_Message_t rxMsg; // Message storage
60
volatile uint8_t rxMsgFull;   // Synchronization flag
69
volatile uint8_t rxMsgFull;   // Synchronization flag
61
 
-
 
62
//uint16_t actualElevationValue;
-
 
63
//uint16_t desiredElevationValue;
-
 
64
//uint16_t actualAzimuthValue;
-
 
65
//uint16_t desiredAzimuthValue;
-
 
66
 
70
 
67
// For calculating average feedback measurement
71
// For calculating average feedback measurement
68
uint16_t azimuthReadout[ AVERAGE_SIZE ];
72
uint16_t azimuthReadout[ AVERAGE_SIZE ];
69
//uint16_t elevationReadout[ AVERAGE_SIZE];
-
 
70
 
73
 
71
uint16_t azimuthCalibration;
74
uint16_t azimuthCalibration;
72
 
75
 
73
// CAN message reception callback.
-
 
74
// This function runs with interrupts disabled, keep it as short as possible.
76
/*-----------------------------------------------------------------------------
75
void can_receive( Can_Message_t *msg ) {
-
 
76
    if (!rxMsgFull) {
77
 * Declarations
77
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
78
 *---------------------------------------------------------------------------*/
78
        rxMsgFull = 1;
-
 
79
    }
79
 
80
}
80
/**
-
 
81
 * calibration
-
 
82
 * Sets and gets calibration data from EEPROM
81
 
83
 *
82
// Calibration function
84
 * @param mode: set /get
83
// mode: set / get
85
 * @param value
84
// value:
86
 * @return value
-
 
87
 */
85
int16_t calibration( uint8_t mode, uint16_t value );
88
int16_t calibration( uint8_t mode, uint16_t value );
86
 
89
 
87
// Turn rotor
90
// Turn rotor
88
// position: 0-1024
91
// position: 0-1024
-
 
92
/**
-
 
93
 * turn
-
 
94
 * Turns rotor to given position
-
 
95
 * FIXME implement this function
-
 
96
 *
-
 
97
 * @param position
-
 
98
 * @return
-
 
99
 */
89
uint8_t turn( uint16_t position );
100
uint8_t turn( uint16_t position );
90
 
101
 
-
 
102
/**
91
// Get position
103
 * getPosition
-
 
104
 * Calculates the antenna position
92
// Gets the average value for compensation of distorsions
105
 * Uses a number of the latest adc readings
-
 
106
 * and gets the avarage value
-
 
107
 *
-
 
108
 * @param void
-
 
109
 * @return position
-
 
110
 */
93
uint16_t getPosition( void );
111
uint16_t getPosition( void );
94
 
112
 
-
 
113
/**
-
 
114
 * initAdcFeedback
95
// Initiate ADC
115
 * Starts the ADC
-
 
116
 *
-
 
117
 * @param void
-
 
118
 * @return void
-
 
119
 */
96
void initAdcFeedback( void );
120
void initAdcFeedback( void );
97
 
121
 
-
 
122
/**
-
 
123
 * readFeedback
98
// Read antenna feedback from ADC
124
 * Gets antenna position from ADC and
-
 
125
 * puts in arrary for later calculations
-
 
126
 *
-
 
127
 * @param void
-
 
128
 * @return void
-
 
129
 */
99
void readFeedback( void );
130
void readFeedback( void );
100
 
131
 
-
 
132
/**
101
// Control rotation relays
133
 * controlRelay
-
 
134
 * Control the relay that turns the rotor
-
 
135
 *
-
 
136
 * @param direction
-
 
137
 * @return void
-
 
138
 */
102
void controlRelay( uint8_t direction );
139
void controlRelay( uint8_t direction );
103
 
140
 
-
 
141
/**
-
 
142
 * sendStatus
104
// Sends antennas position on CAN
143
 * Sends antennas position on CAN bus
-
 
144
 *
-
 
145
 * @param void
-
 
146
 * @return void
-
 
147
 */
105
void sendStatus( void );
148
void sendStatus( void );
106
 
149
 
-
 
150
// CAN message reception callback.
-
 
151
// This function runs with interrupts disabled, keep it as short as possible.
-
 
152
void can_receive( Can_Message_t *msg ) {
-
 
153
    if (!rxMsgFull) {
-
 
154
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
-
 
155
        rxMsgFull = 1;
-
 
156
    }
-
 
157
}
107
 
158
 
-
 
159
/*-----------------------------------------------------------------------------
-
 
160
 * Main Program
-
 
161
 *---------------------------------------------------------------------------*/
108
int main( void )
162
int main( void )
109
{
163
{
110
    // Enable interrupts as early as possible
164
    // Enable interrupts as early as possible
111
    sei();
165
    sei();
112
   
166
   
113
    Timer_Init();
167
    Timer_Init();
-
 
168
 
-
 
169
    DDRD |= (1 << PD1)|(1 << PD2);
-
 
170
    PORTD |= (1 << PD1)|(1 << PD2);
114
   
171
 
115
    // Setup ADC
172
    // Setup ADC
116
    initAdcFeedback();
173
    initAdcFeedback();
117
   
174
   
118
    Can_Message_t txMsg;
175
    Can_Message_t txMsg;
119
    txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
176
    txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
120
    txMsg.DataLength = 4;
177
    txMsg.DataLength = 4;
121
    txMsg.RemoteFlag = 0;
178
    txMsg.RemoteFlag = 0;
122
    txMsg.ExtendedFlag = 1;
179
    txMsg.ExtendedFlag = 1;
123
    txMsg.Data.words[0] = APP_TYPE;
180
    txMsg.Data.words[0] = APP_TYPE;
124
    txMsg.Data.words[1] = APP_VERSION;
181
    txMsg.Data.words[1] = APP_VERSION;
125
   
182
   
126
    // Set up callback for CAN reception, this is optional if only sending is required.
183
    // Set up callback for CAN reception, this is optional if only sending is required.
127
    BIOS_CanCallback = &can_receive;
184
    BIOS_CanCallback = &can_receive;
128
    // Send CAN_NMT_APP_START
185
    // Send CAN_NMT_APP_START
129
    BIOS_CanSend(&txMsg);
186
    BIOS_CanSend(&txMsg);
130
   
187
   
131
    // Read calibration value from eeprom
188
    // Read calibration value from eeprom
132
    azimuthCalibration = eeprom_read_word( CALIBRATE_AZIMUTH );
189
    azimuthCalibration = eeprom_read_word( CALIBRATE_AZIMUTH );
133
   
190
   
134
    // Timer for reading position feedback
191
    // Timer for reading position feedback
135
    Timer_SetTimeout(0, 50, TimerTypeFreeRunning, 0);
192
    Timer_SetTimeout(0, 50, TimerTypeFreeRunning, 0);
-
 
193
    Timer_SetTimeout(1, 1000, TimerTypeFreeRunning, 0);
136
 
194
 
-
 
195
    sendStatus();
137
   
196
 
138
    while (1) {
197
    while (1) {
139
        if (Timer_Expired(0)) {
198
        if (Timer_Expired(0)) {
140
            // Periodicly read antennas position
199
            // Periodicly read antennas position
141
            readFeedback();
200
            readFeedback();
142
        }
201
        }
-
 
202
        if (Timer_Expired(1)) {
-
 
203
            // Send antennas position
-
 
204
            sendStatus();
-
 
205
        }
143
       
206
       
-
 
207
        /* If any messages is received */
144
        if (rxMsgFull) {
208
        if (rxMsgFull) {
145
 
209
 
146
            switch (rxMsg.Id){
210
            switch ( rxMsg.Id ){
-
 
211
                case MSG_CAL_SET:
147
                case MSG_CAL_SET: // Set calibration value
212
                    // Set calibration value
148
                    if( 2 == rxMsg.DataLength ){
213
                    if( 2 == rxMsg.DataLength ){
-
 
214
 
149
                        calibration( SET, rxMsg.Data.words[0] );
215
                        calibration( SET, rxMsg.Data.words[0] );
150
                    }
216
                    }
-
 
217
                   
151
                    break;
218
                    break;
152
                   
219
                   
-
 
220
                case MSG_CAL_GET:
153
                case MSG_CAL_GET: // Get calibration value
221
                    // Get calibration value
154
                    if( 0 == rxMsg.DataLength ){
222
                    if( 0 == rxMsg.DataLength ){
-
 
223
 
-
 
224
                        txMsg.Id = MSG_CAL_RET;
-
 
225
                        txMsg.DataLength = 2;
-
 
226
                        txMsg.Data.words[0] = calibration( GET, 0 );
-
 
227
 
-
 
228
                        BIOS_CanSend(&txMsg);
155
                       
229
                    }
156
                    }
230
                   
157
                    break;
231
                    break;
158
                   
232
                   
-
 
233
                case MSG_ABS:
159
                case MSG_ABS: // Start turning to absolute position
234
                    // Start turning to absolute position
160
                    if( 2 == rxMsg.DataLength ){
235
                    if( 2 == rxMsg.DataLength ){
161
                       
236
 
-
 
237
                        //FIXME implement this
-
 
238
                    }
-
 
239
                   
-
 
240
                    break;
-
 
241
                   
-
 
242
                case MSG_REL:
-
 
243
                    // Start turning to relative position
-
 
244
                    if( 2 == rxMsg.DataLength ){
-
 
245
 
-
 
246
                        //FIXME implement this
162
                    }
247
                    }
163
                    break;
-
 
164
                   
248
                   
165
                case MSG_REL: // Start turning to relative position
-
 
166
                    if( 2 == rxMsg.DataLength ){
-
 
167
                       
-
 
168
                    }
-
 
169
                    break;
249
                    break;
170
                   
250
                   
171
                case MSG_START: // Start turning
251
                case MSG_START:
-
 
252
                    // Start turning rotor
172
                    if( 1 == rxMsg.DataLength ){
253
                    if( 1 == rxMsg.DataLength ){
-
 
254
 
173
                        // First data byte decides direction
255
                        // First data byte decides direction
174
                        controlRelay( rxMsg.Data.bytes[0] );
256
                        controlRelay( rxMsg.Data.bytes[0] );
175
                    }
257
                    }
-
 
258
                   
176
                    break;
259
                    break;
177
                   
260
                   
178
                case MSG_STOP: // Stop turning
261
                case MSG_STOP:
179
                    if( 1 == rxMsg.DataLength ){
262
                    // Stop turning rotor
-
 
263
                   
180
                        controlRelay( ROTATE_STOP );
264
                    controlRelay( ROTATE_STOP );
181
                    }
265
                   
182
                    break;
266
                    break;
-
 
267
                   
183
                case MSG_STATUS: // Get position
268
                case MSG_STATUS:
-
 
269
                    // Get position
184
                    if( 0 == rxMsg.DataLength ){
270
                    if( 0 == rxMsg.DataLength ){
185
                        sendStatus();
271
                        sendStatus();
186
                    }
272
                    }
-
 
273
                   
187
                    break;
274
                    break;
188
                   
275
                   
189
                default:
276
                default:
190
                    break;
277
                    break;
191
            }
278
            }
192
 
279
 
193
            rxMsgFull = 0; //  
280
            rxMsgFull = 0;
194
        }
281
        }
195
    }
282
    }
196
   
283
   
197
    return 0;
284
    return 0;
198
}
285
}
199
 
286
 
-
 
287
/*-----------------------------------------------------------------------------
-
 
288
 * Definitions
-
 
289
 *---------------------------------------------------------------------------*/
200
 
290
 
201
int16_t calibration( uint8_t mode, uint16_t value )
291
int16_t calibration( uint8_t mode, uint16_t value )
202
{
292
{
203
    // set / get calibration value
293
    // set / get calibration value
204
    if( SET == mode ){
294
    if( SET == mode ){
205
        eeprom_write_word( CALIBRATE_AZIMUTH, value );
295
        eeprom_write_word( CALIBRATE_AZIMUTH, value );
206
        azimuthCalibration = value;
296
        azimuthCalibration = value;
207
   
297
   
208
    }else if( GET == mode ){
298
    }else if( GET == mode ){
209
        return azimuthCalibration;
299
        return azimuthCalibration;
210
    }
300
    }
211
    return 0;
301
    return 0;
212
}
302
}
213
 
303
 
214
uint8_t turn( uint16_t position )
304
uint8_t turn( uint16_t position )
215
{
305
{
-
 
306
    //FIXME implement this
216
    // start relay
307
    // start relay
217
    // read feedback
308
    // read feedback
218
    // callibrate measurement
309
    // callibrate measurement
219
   
310
   
220
    while(0){
311
    while(0){
221
       
312
       
222
    }
313
    }
223
    return 0;
314
    return 0;
224
}
315
}
225
 
316
 
226
uint16_t getPosition( void )
317
uint16_t getPosition( void )
227
{
318
{
228
    uint16_t position = 0;
319
    uint16_t position = 0;
229
   
320
   
230
    // Get average value of position
321
    // Get average value of position
231
    for( uint8_t i=0; i < AVERAGE_SIZE; i++ ){
322
    for( uint8_t i=0; i < AVERAGE_SIZE; i++ ){
232
        position += azimuthReadout[i];
323
        position += azimuthReadout[i];
233
    }
324
    }
234
   
325
   
-
 
326
    // Calculate average
235
    position = position >> AVERAGE_SIZE_SHIFT;
327
    position = position >> AVERAGE_SIZE_SHIFT;
-
 
328
 
-
 
329
    // Convert to degrees, gives about 379 degrees
-
 
330
    position /= 3;
-
 
331
 
-
 
332
    // Calibrate
236
    position += azimuthCalibration;
333
    position += (int16_t)azimuthCalibration;
237
   
334
   
238
    return position;
335
    return position;
239
}
336
}
240
 
337
 
241
void initAdcFeedback( void )
338
void initAdcFeedback( void )
Line 253... Line 350...
253
    ADMUX |= ( 1 << REFS0 );
350
    ADMUX |= ( 1 << REFS0 );
254
    ADMUX &= ~( 1 << REFS1 );
351
    ADMUX &= ~( 1 << REFS1 );
255
   
352
   
256
    // Right adjust the result
353
    // Right adjust the result
257
    ADMUX &= ~( 1 << ADLAR );
354
    ADMUX &= ~( 1 << ADLAR );
258
   
-
 
259
//  // Auto Trigger
-
 
260
//  ADCSRA |= ( 1 << ADATE );
-
 
261
   
355
   
262
    // Disable digital input
356
    // Disable digital input
263
    DIDR0 |= ( 1 << ADC5D )|( 1 << ADC4D );
357
    DIDR0 |= ( 1 << ADC5D )|( 1 << ADC4D );
264
   
358
   
265
    // Wake up ADC and enable it
359
    // Wake up ADC and enable it
Line 270... Line 364...
270
    ADCSRA |= ( 1 << ADSC );
364
    ADCSRA |= ( 1 << ADSC );
271
}
365
}
272
 
366
 
273
void controlRelay( uint8_t direction )
367
void controlRelay( uint8_t direction )
274
{
368
{
275
    if( ROTATE_PLUS == direction ){ // Turn clockwise
369
    if( ROTATE_PLUS == direction ){
-
 
370
        // Turn CW
276
        PORTD &= ~(1 << PD2);
371
        PORTD &= ~(1 << PD2);
277
        PORTD |= (1 << PD1);
372
        PORTD |= (1 << PD1);
278
    }else if ( ROTATE_MINUS == direction ){ // Turn counter clockwise
373
    }else if ( ROTATE_MINUS == direction ){
-
 
374
        // Turn CCW
279
        PORTD &= ~(1 << PD1);
375
        PORTD &= ~(1 << PD1);
280
        PORTD |= (1 << PD2);
376
        PORTD |= (1 << PD2);
281
    }else{
377
    }else{
282
        // Stop azimuth rotor
378
        // Stop azimuth rotor
283
        PORTD |= (1 << PD1);
379
        PORTD |= (1 << PD1);
Line 287... Line 383...
287
 
383
 
288
void readFeedback( void )
384
void readFeedback( void )
289
{
385
{
290
    static uint8_t azimuthArrayPosition = 0;
386
    static uint8_t azimuthArrayPosition = 0;
291
 
387
 
-
 
388
    // Wait for ADC conversion to complete
292
    while( ADCSRA & ( 1 << ADSC )){} // Wait for conversion to complete
389
    while( ADCSRA & ( 1 << ADSC )){}
293
   
390
   
-
 
391
    // Put readout in ringbuffer
294
    azimuthReadout[ azimuthArrayPosition ] = ADCW;
392
    azimuthReadout[ azimuthArrayPosition ] = ADCW;
295
    azimuthArrayPosition++;
393
    azimuthArrayPosition++;
-
 
394
   
296
    if( AVERAGE_SIZE <= azimuthArrayPosition ){
395
    if( AVERAGE_SIZE <= azimuthArrayPosition ){
297
        azimuthArrayPosition = 0;
396
        azimuthArrayPosition = 0;
298
    }
397
    }
299
   
398
   
300
    // Start next conversion
399
    // Start next conversion
301
    ADCSRA |= ( 1 << ADSC );
400
    ADCSRA |= ( 1 << ADSC );
302
}
401
}
303
 
402
 
304
void sendStatus( void )
403
void sendStatus( void )
305
{
404
{
-
 
405
    // Gets antennas position and sends on CAN bus
306
    Can_Message_t txMsg;
406
    Can_Message_t txMsg;
307
   
407
   
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 );
408
    txMsg.Id = 0x1f8f0100UL; //FIXME id should not be defined here
309
   
409
   
310
    txMsg.DataLength = 2;
410
    txMsg.DataLength = 2;
311
    txMsg.RemoteFlag = 0;
411
    txMsg.RemoteFlag = 0;
312
    txMsg.ExtendedFlag = 1;
412
    txMsg.ExtendedFlag = 1;
313
   
413
   
314
    txMsg.Data.words[ 0 ] = getPosition();
414
    txMsg.Data.words[ 0 ] = getPosition();
315
   
415
   
316
    BIOS_CanSend( &txMsg );
416
    BIOS_CanSend( &txMsg );
317
   
417
   
318
}
418
}
-
 
419