Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
171 eqlazer 1
/**
177 eqlazer 2
 * CAN Relay.
3
 *
4
 *
5
 * @date    2006-12-17
6
 * @author  Erik Larsson
7
 *
185 eqlazer 8
 *   Observera! Applikationen är endast testad på labplatta med m88, pot och lysdiod
177 eqlazer 9
 *
175 eqlazer 10
 *   ADC=Vin*1024/Vref
176 eqlazer 11
 *   Vout=( 10 mV/C )( Temperature C ) + 500 mV
175 eqlazer 12
 *
190 eqlazer 13
 *  Transmitts: DATA: <temperature low byte> <temperature high byte> <relay status> <failsafe mode>
176 eqlazer 14
 *
184 eqlazer 15
 *
171 eqlazer 16
 */
17
 
192 eqlazer 18
#define DEBUG           1 /* Prints debug messages to uart */
19
#define TWO_BUTTON_MODE 1 /* If using two (or just one but nothing more) auxiliary buttons */
177 eqlazer 20
 
171 eqlazer 21
/*-----------------------------------------------------------------------------
22
 * Includes
23
 *---------------------------------------------------------------------------*/
24
/* system files */
25
#include <avr/io.h>
26
#include <avr/interrupt.h>
27
#include <avr/wdt.h>
28
#include <stdio.h>
29
/* lib files */
30
#include <can.h>
31
#include <serial.h>
32
#include <timebase.h>
187 eqlazer 33
 
34
#include <tc1047.h>
35
 
177 eqlazer 36
/* defines */
187 eqlazer 37
#define RELAY_OFF           0x01
38
#define RELAY_ON            0x02
39
#define FAILSAFE_MODE       0x0F
40
#define FAILSAFE_TRESHOLD   60  /* Degrees when nodeRelay goes into failsafe mode */
171 eqlazer 41
 
187 eqlazer 42
#define RELAY_CMD_GET       0x1200
43
#define RELAY_CMD_SEND      0x1201
44
#define RELAY_CMD_ON        0x01
45
#define RELAY_CMD_OFF       0x02
46
#define RELAY_CMD_TOGGLE    0x03
47
#define RELAY_CMD_STATUS    0x04
48
#define RELAY_CMD_RESET     0x05
49
#define STATUS_SEND_PERIOD  10000 /* milliseconds */
192 eqlazer 50
#define FAILSAFE_SEND_PERIOD    10000 /* milliseconds */
51
#define BOUNCE_TIME         10 /* milliseconds */
52
#define BUTTON_ID           0x1202
53
#define BUTTON1             1
54
#define BUTTON2             2
187 eqlazer 55
 
192 eqlazer 56
/*-------------------------------------------------------------------------
57
 * Global variables
58
 * -----------------------------------------------------------------------*/
59
#if TWO_BUTTON_MODE
60
Can_Message_t txMsg_Button;
61
#endif
62
 
187 eqlazer 63
/*----------------------------------------------------------------------------
64
 * Functions
65
 * -------------------------------------------------------------------------*/
66
uint8_t relayOff();
67
uint8_t relayOn();
68
void relayFailsafe();
69
 
192 eqlazer 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
#if DEBUG
89
        printf("Button 1 pressed\n");
90
#endif
91
    }else if( (PIND & (1<<PD6)) == 1){
92
        if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){
93
            /* No bounce, send message */
94
            txMsg_Button.Id = BUTTON_ID;
95
            txMsg_Button.DataLength = 1;
96
            txMsg_Button.Data.bytes[0] = BUTTON1;
97
#if DEBUG
98
            printf("Button 1 pressed: message sent\n");
99
#endif
100
            return;
101
        }else{
102
            /* Just bounces, ignore it */
103
#if DEBUG
104
            printf("Button 1 just bounced\n");
105
#endif
106
            return;
107
        }
108
    }
109
    if( (PIND & (1<<PD7)) == 0){
110
        /* Button pressed */
111
        buttonTime[1] = Timebase_CurrentTime();
112
#if DEBUG
113
        printf("Button 2 pressed\n");
114
#endif
115
    }else if( (PIND & (1<<PD7)) == 1){
116
        if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){
117
            /* No bounce, send message */
118
            txMsg_Button.Id = BUTTON_ID;
119
            txMsg_Button.DataLength = 1;
120
            txMsg_Button.Data.bytes[0] = BUTTON2;
121
#if DEBUG
122
            printf("Button 2 pressed: message sent\n");
123
#endif
124
            return;
125
        }else{
126
            /* Just bounces, ignore it */
127
#if DEBUG
128
            printf("Button 2 just bounced\n");
129
#endif
130
            return;
131
        }
132
    }
133
}
134
#endif
135
 
136
//ISR( ADC_vect )
137
//{
138
    /*
139
     * ADC conversion completed
140
     */
141
    // TODO använd denna rutin för att läsa värde när omvandlingen är klar
142
 
143
//}
144
 
171 eqlazer 145
/*-----------------------------------------------------------------------------
146
 * Main Program
147
 *---------------------------------------------------------------------------*/
148
int main(void) {
149
 
150
    uint8_t relayStatus;
187 eqlazer 151
    uint32_t boardTemperature = 0;
171 eqlazer 152
 
187 eqlazer 153
    adcTemperatureInit();
154
 
176 eqlazer 155
    Timebase_Init();
185 eqlazer 156
#if DEBUG
176 eqlazer 157
    Serial_Init();
185 eqlazer 158
#endif
192 eqlazer 159
 
160
#if TWO_BUTTON_MODE
161
    /*
162
     * Initialize buttons
163
     * It is possible to use ie. sensors instead
164
     * but then change this
165
     */
166
    /* Set as input and enable pull-up */
167
    DDRD &= ~( (1<<DDD6)|(1<<DDD7) );
168
    PORTD |= (1<<PD6)|(1<<PD7);
169
 
170
    /* Enable IO-pin interrupt */
171
    PCICR |= (1<<PCIE1);
172
    /* Unmask PD6 and PD7 */
173
    PCMSK2 |= (1<<PCINT22) | (1<<PCINT23);
174
#endif
176 eqlazer 175
    sei();
171 eqlazer 176
 
176 eqlazer 177
    /* Turn relay off */
187 eqlazer 178
    relayStatus = relayOff();
175 eqlazer 179
 
184 eqlazer 180
#if DEBUG
176 eqlazer 181
    printf("\n------------------------------------------------------------\n");
182
    printf(  "   CAN: Relay\n");
183
    printf(  "------------------------------------------------------------\n");
171 eqlazer 184
 
185
 
176 eqlazer 186
    printf("CanInit...");
187
    if (Can_Init() != CAN_OK) {
188
        printf("FAILED!\n");
175 eqlazer 189
    }else{
190
        printf("OK!\n");
191
    }
185 eqlazer 192
#else
193
    Can_Init();
184 eqlazer 194
#endif
175 eqlazer 195
    uint32_t timeStamp = 0;
171 eqlazer 196
 
175 eqlazer 197
    Can_Message_t txMsg;
198
    Can_Message_t rxMsg;
187 eqlazer 199
    txMsg.Id = RELAY_CMD_SEND;
175 eqlazer 200
    txMsg.RemoteFlag = 0;
201
    txMsg.ExtendedFlag = 1;
187 eqlazer 202
    txMsg.DataLength = 3;
175 eqlazer 203
 
204
    /* main loop */
205
    while (1) {
206
        /* service the CAN routines */
207
        Can_Service();
208
 
209
        /* check if any messages have been received */
210
        while (Can_Receive(&rxMsg) == CAN_OK) {
171 eqlazer 211
            /* This relay is adressed*/
187 eqlazer 212
            if( rxMsg.Id == RELAY_CMD_GET ){
171 eqlazer 213
 
187 eqlazer 214
                if( rxMsg.Data.bytes[0] == RELAY_CMD_ON ){
171 eqlazer 215
                    /* Turn relay on */
187 eqlazer 216
                    relayStatus = relayOn();
171 eqlazer 217
 
187 eqlazer 218
                }else if(rxMsg.Data.bytes[0] == RELAY_CMD_OFF){
219
                    /* Turn relay off */
220
                    relayStatus = relayOff();
175 eqlazer 221
 
187 eqlazer 222
                }else if(rxMsg.Data.bytes[0] == RELAY_CMD_TOGGLE ){
223
                    /* Toggle relay */
171 eqlazer 224
 
187 eqlazer 225
                    if(relayStatus == RELAY_OFF){
226
                        relayStatus = relayOn();
227
                    }else{
228
                        relayStatus = relayOff();
229
                    }
171 eqlazer 230
 
187 eqlazer 231
                }else if(rxMsg.Data.bytes[0] == RELAY_CMD_STATUS){
232
                    /* Send relay status to CAN */
175 eqlazer 233
 
187 eqlazer 234
                    boardTemperature = getTC1047temperature();
171 eqlazer 235
 
190 eqlazer 236
                    if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
187 eqlazer 237
                        relayFailsafe();
238
                    }else{
239
                        txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
240
                        txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
241
                        txMsg.Data.bytes[2] = relayStatus;
171 eqlazer 242
 
187 eqlazer 243
                        Can_Send( &txMsg );
244
                    }
245
                }
246
            }
247
        }
248
 
249
        if( Timebase_PassedTimeMillis(timeStamp) >= STATUS_SEND_PERIOD ){
250
            timeStamp = Timebase_CurrentTime();
251
            /* Send relay status to CAN */
252
 
253
            boardTemperature = getTC1047temperature();
254
 
190 eqlazer 255
            if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
187 eqlazer 256
                relayFailsafe();
257
            }else{
258
                txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
259
                txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
260
                txMsg.Data.bytes[2] = relayStatus;
261
 
262
                Can_Send( &txMsg );
184 eqlazer 263
#if DEBUG
187 eqlazer 264
                printf("Periodic message sent...\n");
265
                printf("Temperature: %d\nRelay status: %u\n", boardTemperature, relayStatus);
184 eqlazer 266
#endif
187 eqlazer 267
            }
268
        }
269
    }
270
    return 0;
271
}
176 eqlazer 272
 
187 eqlazer 273
uint8_t relayOff()
274
{
275
    /* Set as output and sink */
276
    PORTC &= ~(1<<PC1);
277
    DDRC |= (1<<DDC1);
175 eqlazer 278
 
184 eqlazer 279
#if DEBUG
187 eqlazer 280
    printf("relay turned off\n");
184 eqlazer 281
#endif
176 eqlazer 282
 
187 eqlazer 283
    return RELAY_OFF;
284
}
171 eqlazer 285
 
187 eqlazer 286
uint8_t relayOn()
287
{
288
    /* Set as input and enable pull-up */
289
    DDRC &= ~(1<<DDC1);
290
    PORTC |= (1<<PC1);
184 eqlazer 291
 
187 eqlazer 292
#if DEBUG
293
    printf("relay turned on\n");
294
#endif
184 eqlazer 295
 
187 eqlazer 296
    return RELAY_ON;
297
}
184 eqlazer 298
 
187 eqlazer 299
void relayFailsafe()
300
{
301
    uint8_t relayStatus;
302
    uint32_t boardTemperature = 0, timeStamp = 0;
184 eqlazer 303
 
187 eqlazer 304
    Can_Message_t txMsg;
305
    Can_Message_t rxMsg;
306
    txMsg.Id = RELAY_CMD_SEND;
307
    txMsg.RemoteFlag = 0;
308
    txMsg.ExtendedFlag = 1;
309
    txMsg.DataLength = 4;
184 eqlazer 310
 
187 eqlazer 311
    relayStatus = relayOff();
184 eqlazer 312
 
187 eqlazer 313
    while(1){
314
        /* service the CAN routines */
315
        Can_Service();
184 eqlazer 316
 
187 eqlazer 317
        /* check if any messages have been received */
318
        while (Can_Receive(&rxMsg) == CAN_OK) {
319
            /* This relay is adressed*/
320
            if( rxMsg.Id == RELAY_CMD_GET ){
321
                if( rxMsg.Data.bytes[0] == RELAY_CMD_RESET ){
322
                    /* Return from failsafe mode */
192 eqlazer 323
                    return;
171 eqlazer 324
                }
325
            }
326
        }
327
 
187 eqlazer 328
        if( Timebase_PassedTimeMillis(timeStamp) >= FAILSAFE_SEND_PERIOD ){
171 eqlazer 329
            timeStamp = Timebase_CurrentTime();
187 eqlazer 330
            /* Send relay status to CAN */
190 eqlazer 331
#if DEBUG
332
            printf("Failsafe mode!\n");
333
#endif
187 eqlazer 334
            boardTemperature = getTC1047temperature();
184 eqlazer 335
 
187 eqlazer 336
            txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
337
            txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
185 eqlazer 338
            txMsg.Data.bytes[2] = relayStatus;
187 eqlazer 339
            txMsg.Data.bytes[3] = FAILSAFE_MODE;
184 eqlazer 340
 
341
            Can_Send( &txMsg );
171 eqlazer 342
        }
177 eqlazer 343
    }
171 eqlazer 344
}
175 eqlazer 345