Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
207 eqlazer 1
/**
2
 * CanBlinds.
3
 * Takes incomming packages and adjusts PWM output.
4
 * Input: -128 to +127
249 eqlazer 5
 * Position msg: <byte0 BLINDS_CMD> <byte1 position> <byte2 servo number>
6
 * Turning msg: <byte0 START/STOP> <byte 1 direction> <byte2 servo number>
207 eqlazer 7
 *
214 eqlazer 8
 * @date    2001-01-01
207 eqlazer 9
 * @author  Erik Larsson
249 eqlazer 10
 *
11
 * TODO fixa en ordentlig failsafe som kan bryta matningen till servona
207 eqlazer 12
 */
13
 
246 eqlazer 14
#define TWO_BUTTON_MODE 0 /* If using two (or just one but nothing more) auxiliary buttons */
207 eqlazer 15
 
16
/*-----------------------------------------------------------------------------
17
 * Includes
18
 *---------------------------------------------------------------------------*/
19
/* system files */
20
#include <avr/io.h>
21
#include <avr/interrupt.h>
22
#include <avr/wdt.h>
23
#include <stdio.h>
24
/* lib files */
25
#include <can.h>
26
#include <timebase.h>
27
 
246 eqlazer 28
#include <tc1047.h>
214 eqlazer 29
#include <rc_servo.h>
207 eqlazer 30
 
31
/* defines */
32
#define FAILSAFE_MODE       0x0F
214 eqlazer 33
#define FAILSAFE_TRESHOLD   60  /* Degrees celcius when nodeBlinds goes into failsafe mode */
207 eqlazer 34
 
214 eqlazer 35
#define BLINDS_CMD_GET      0x1300
36
#define BLINDS_CMD_SEND     0x1301
207 eqlazer 37
 
38
#define BLINDS_CMD_ABS      0x01 /* Absolute position */
39
#define BLINDS_CMD_REL      0x02 /* Relative position */
40
#define BLINDS_CMD_START    0x03 /* Start turning RC-servo */
41
#define BLINDS_CMD_STOP     0x04 /* Stop turning RC-servo */
42
#define BLINDS_CMD_RESET    0x05
214 eqlazer 43
#define BLINDS_CMD_STATUS   0x06
207 eqlazer 44
 
214 eqlazer 45
#define BLINDS_TURN_STOP    0x00
46
#define BLINDS_TURN_LEFT    0x01
47
#define BLINDS_TURN_RIGHT   0x02
207 eqlazer 48
 
214 eqlazer 49
#define STEPS_PER_TURN_PERIOD 10 /* number of steps for each adjustment */
50
#define TURN_PERIOD         100 /* milliseconds */
207 eqlazer 51
#define STATUS_SEND_PERIOD  10000 /* milliseconds */
52
#define FAILSAFE_SEND_PERIOD    10000 /* milliseconds */
53
#define BOUNCE_TIME         10 /* milliseconds */
54
#define BUTTON_ID           0x1202
55
#define BUTTON1             1
56
#define BUTTON2             2
57
 
58
/*-------------------------------------------------------------------------
59
 * Global variables
60
 * -----------------------------------------------------------------------*/
61
#if TWO_BUTTON_MODE
62
Can_Message_t txMsg_Button;
63
#endif
64
 
65
/*----------------------------------------------------------------------------
66
 * Functions
67
 * -------------------------------------------------------------------------*/
68
void blindsFailsafe();
69
 
70
/*----------------------------------------------------------------------------
71
 * Interrupt routines
72
 * -------------------------------------------------------------------------*/
73
#if TWO_BUTTON_MODE
74
ISR( PCINT2_vect )
75
{
76
    /*
77
     * Auxiliary button pressed and released
78
     * Check time between press and release to eliminate bounces
79
     */
80
    static uint32_t buttonTime[2];
81
 
82
    txMsg_Button.RemoteFlag = 0;
83
    txMsg_Button.ExtendedFlag = 1;
84
 
85
    if( (PIND & (1<<PD6)) == 0){
86
        /* Button pressed */
87
        buttonTime[0] = Timebase_CurrentTime();
88
    }else if( (PIND & (1<<PD6)) == 1){
89
        if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){
90
            /* No bounce, send message */
91
            txMsg_Button.Id = BUTTON_ID;
92
            txMsg_Button.DataLength = 1;
93
            txMsg_Button.Data.bytes[0] = BUTTON1;
94
            return;
95
        }else{
96
            /* Just bounces, ignore it */
97
            return;
98
        }
99
    }
100
    if( (PIND & (1<<PD7)) == 0){
101
        /* Button pressed */
102
        buttonTime[1] = Timebase_CurrentTime();
103
    }else if( (PIND & (1<<PD7)) == 1){
104
        if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){
105
            /* No bounce, send message */
106
            txMsg_Button.Id = BUTTON_ID;
107
            txMsg_Button.DataLength = 1;
108
            txMsg_Button.Data.bytes[0] = BUTTON2;
109
            return;
110
        }else{
111
            /* Just bounces, ignore it */
112
            return;
113
        }
114
    }
115
}
116
#endif
117
 
118
/*-----------------------------------------------------------------------------
119
 * Main Program
120
 *---------------------------------------------------------------------------*/
121
int main(void) {
122
 
214 eqlazer 123
    uint8_t blindsStatus, /* Position (-128 to 127) */
249 eqlazer 124
            servoToTurn,
214 eqlazer 125
            turnDirection = BLINDS_TURN_STOP; /* Specifies direction to turn or stopped */
207 eqlazer 126
    uint32_t boardTemperature = 0;
214 eqlazer 127
    uint32_t timeStamp = 0, timeStampTurn = 0;
207 eqlazer 128
 
129
    adcTemperatureInit();
130
    Timebase_Init();
214 eqlazer 131
    rcServoInit();
207 eqlazer 132
 
133
#if TWO_BUTTON_MODE
134
    /*
135
     * Initialize buttons
136
     * It is possible to use ie. sensors instead
137
     * but then change this
138
     */
139
    /* Set as input and enable pull-up */
140
    DDRD &= ~( (1<<DDD6)|(1<<DDD7) );
141
    PORTD |= (1<<PD6)|(1<<PD7);
142
 
143
    /* Enable IO-pin interrupt */
144
    PCICR |= (1<<PCIE1);
145
    /* Unmask PD6 and PD7 */
146
    PCMSK2 |= (1<<PCINT22) | (1<<PCINT23);
147
#endif
148
    sei();
149
    Can_Init();
150
 
151
    Can_Message_t txMsg;
152
    Can_Message_t rxMsg;
153
    txMsg.Id = BLINDS_CMD_SEND;
154
    txMsg.RemoteFlag = 0;
155
    txMsg.ExtendedFlag = 1;
156
    txMsg.DataLength = 3;
157
 
158
    /* main loop */
159
    while (1) {
160
        /* service the CAN routines */
161
        Can_Service();
162
 
163
        /* check if any messages have been received */
164
        while (Can_Receive(&rxMsg) == CAN_OK) {
165
            /* This node that control a servo is adressed */
166
            if( rxMsg.Id == BLINDS_CMD_GET ){
167
 
168
                if( rxMsg.Data.bytes[0] == BLINDS_CMD_ABS ){
169
                    /* Set absolute position to servo */
249 eqlazer 170
                    setPosition( rxMsg.Data.bytes[1], rxMsg.Data.bytes[2] );
207 eqlazer 171
 
172
                }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_REL){
173
                    /* Set relative position to servo */
249 eqlazer 174
                    alterPosition( rxMsg.Data.bytes[1], rxMsg.Data.bytes[2] );
207 eqlazer 175
 
176
                }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_START ){
177
                    /* Start turning the servo */
214 eqlazer 178
                    turnDirection = rxMsg.Data.bytes[1];
249 eqlazer 179
                    servoToTurn = rxMsg.Data.bytes[2];
207 eqlazer 180
 
181
                }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_STOP ){
182
                    /* Stop turning */
214 eqlazer 183
                    turnDirection = BLINDS_TURN_STOP;
207 eqlazer 184
 
185
                }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_STATUS){
186
                    /* Send blinds status to CAN */
187
                    boardTemperature = getTC1047temperature();
188
 
189
                    if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
190
                        blindsFailsafe();
191
                    }else{
192
                        txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
193
                        txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
249 eqlazer 194
                        txMsg.Data.bytes[2] = 0x00;
195
#if NUMBER_OF_RCS >0
196
                        txMsg.Data.bytes[3] = getPosition(1);
197
#endif
198
#if NUMBER_OF_RCS >1
199
                        txMsg.Data.bytes[4] = getPosition(2);
200
#endif
201
#if NUMBER_OF_RCS >2
202
                        txMsg.Data.bytes[5] = getPosition(3);
203
#endif
204
                        txMsg.DataLength = NUMBER_OF_RCS+3;
207 eqlazer 205
                        Can_Send( &txMsg );
206
                    }
207
                }
208
            }
209
        }
210
 
211
        if( Timebase_PassedTimeMillis(timeStamp) >= STATUS_SEND_PERIOD ){
212
            timeStamp = Timebase_CurrentTime();
213
            /* Send blinds status to CAN */
214
 
215
            boardTemperature = getTC1047temperature();
216
 
217
            if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
218
                blindsFailsafe();
219
            }else{
220
                txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
221
                txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
249 eqlazer 222
                txMsg.Data.bytes[2] = 0x00;
223
#if NUMBER_OF_RCS >0
224
                txMsg.Data.bytes[3] = getPosition(1);
225
#endif
226
#if NUMBER_OF_RCS >1
227
                txMsg.Data.bytes[4] = getPosition(2);
228
#endif
229
#if NUMBER_OF_RCS >2
230
                txMsg.Data.bytes[5] = getPosition(3);
231
#endif
232
                txMsg.DataLength = NUMBER_OF_RCS+3;
207 eqlazer 233
 
234
                Can_Send( &txMsg );
235
            }
236
        }
214 eqlazer 237
        /* If start turning servo */
238
        if( turnDirection ){
239
            if( Timebase_PassedTimeMillis( timeStampTurn ) >= TURN_PERIOD ){
240
                timeStampTurn = Timebase_CurrentTime();
241
                /* Clockwise or counterclockwise? */
242
                if( turnDirection == BLINDS_TURN_LEFT ){
249 eqlazer 243
                    alterPosition( -STEPS_PER_TURN_PERIOD , servoToTurn);
214 eqlazer 244
                }else if( turnDirection == BLINDS_TURN_RIGHT ){
249 eqlazer 245
                    alterPosition( STEPS_PER_TURN_PERIOD , servoToTurn);
214 eqlazer 246
                }
247
            }
248
        }
207 eqlazer 249
    }
250
    return 0;
251
}
252
 
214 eqlazer 253
void blindsFailsafe() // TODO fixa failsafe, vad ska hända med PWM?
207 eqlazer 254
{
255
    uint8_t relayStatus;
256
    uint32_t boardTemperature = 0, timeStamp = 0;
257
 
258
    Can_Message_t txMsg;
259
    Can_Message_t rxMsg;
260
    txMsg.Id = BLINDS_CMD_SEND;
261
    txMsg.RemoteFlag = 0;
262
    txMsg.ExtendedFlag = 1;
263
    txMsg.DataLength = 4;
264
 
265
    while(1){
266
        /* service the CAN routines */
267
        Can_Service();
268
 
269
        /* check if any messages have been received */
270
        while (Can_Receive(&rxMsg) == CAN_OK) {
271
            /* This relay is adressed*/
272
            if( rxMsg.Id == BLINDS_CMD_GET ){
273
                if( rxMsg.Data.bytes[0] == BLINDS_CMD_RESET ){
274
                    /* Return from failsafe mode */
275
                    return;
276
                }
277
            }
278
        }
279
 
280
        if( Timebase_PassedTimeMillis(timeStamp) >= FAILSAFE_SEND_PERIOD ){
281
            timeStamp = Timebase_CurrentTime();
282
            /* Send relay status to CAN */
283
            boardTemperature = getTC1047temperature();
284
 
285
            txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
286
            txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
249 eqlazer 287
            txMsg.Data.bytes[2] = FAILSAFE_MODE;
288
#if NUMBER_OF_RCS >0
289
            txMsg.Data.bytes[3] = getPosition(1);
290
#endif
291
#if NUMBER_OF_RCS >1
292
            txMsg.Data.bytes[4] = getPosition(2);
293
#endif
294
#if NUMBER_OF_RCS >2
295
            txMsg.Data.bytes[5] = getPosition(3);
296
#endif
297
            txMsg.DataLength = NUMBER_OF_RCS+3;
207 eqlazer 298
 
299
            Can_Send( &txMsg );
300
        }
301
    }
302
}
303