Subversion Repositories HomeAutomation

Rev

Rev 731 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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