Rev 352 | Rev 360 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed
/*** CAN Relay.*** @date 2006-12-17* @author Erik Larsson** ADC=Vin*1024/Vref* Vout=( 10 mV/C )( Temperature C ) + 500 mV** Transmitts: DATA: <temperature low byte> <temperature high byte> <relay status> <failsafe mode>***/#define TWO_BUTTON_MODE 0 /* If using two (or just one but nothing more) auxiliary buttons *//*-----------------------------------------------------------------------------* Includes*---------------------------------------------------------------------------*//* system files */#include <avr/io.h>#include <avr/interrupt.h>#include <stdio.h>#include <avr/wdt.h>/* lib files */#include <bios.h>#include <tc1047.h>#include <funcdefs.h>/* defines */#define GROUP_ID 0x01UL#define RELAY_OFF 0x01UL#define RELAY_ON 0x02UL#define FAILSAFE_MODE 0x0FUL#define FAILSAFE_TRESHOLD 60 /* Degrees when nodeRelay goes into failsafe mode */#define RELAY_CMD_ON 0x01UL#define RELAY_CMD_OFF 0x02UL#define RELAY_CMD_TOGGLE 0x03UL#define RELAY_CMD_STATUS 0x04UL#define RELAY_CMD_RESET 0x05UL#define STATUS_SEND_PERIOD 10000 /* milliseconds */#define FAILSAFE_SEND_PERIOD 10000 /* milliseconds */#define BOUNCE_TIME 10 /* milliseconds */#define BUTTON1 1#define BUTTON2 2/*-------------------------------------------------------------------------* Global variables* -----------------------------------------------------------------------*/#if TWO_BUTTON_MODECan_Message_t txMsg_Button;#endifuint8_t relayStatus, failsafe_flag = 0;uint32_t boardTemperature = 0;Can_Message_t txMsg;/*----------------------------------------------------------------------------* Functions* -------------------------------------------------------------------------*/uint8_t relayOff();uint8_t relayOn();void relayFailsafe();void can_receive(Can_Message_t *msg){uint32_t act;uint32_t m, act_type, group, node;if( ((msg->Id & CLASS_MASK)>>CLASS_MASK_BITS) == CLASS_ACT){act = (msg->Id & TYPE_MASK) >> TYPE_MASK_BITS;act_type = (act & ACT_TYPE_MASK) >> ACT_TYPE_BITS;group = (act & ACT_GROUP_MASK) >> ACT_GROUP_BITS;node = (act & ACT_NODE_MASK) >> ACT_NODE_BITS;if( act_type == ACT_TYPE_RELAY && (group == GROUP_ID || node == NODE_ID) ){if(msg->Data.bytes[0] == RELAY_CMD_ON && !failsafe_flag){// Turn relay onrelayStatus = relayOn();}else if(msg->Data.bytes[0] == RELAY_CMD_OFF && !failsafe_flag){// Turn relay offrelayStatus = relayOff();txMsg.Id = 0x8000111UL; // FIXMEbios->can_send(&txMsg);}else if(msg->Data.bytes[0] == RELAY_CMD_TOGGLE && !failsafe_flag){// Toggle relayif(relayStatus == RELAY_OFF){relayStatus = relayOn();}else{relayStatus = relayOff();txMsg.Id = 0x8000113UL; // FIXMEbios->can_send(&txMsg);}}else if(msg->Data.bytes[0] == RELAY_CMD_STATUS && !failsafe_flag){// Send relay status to CANboardTemperature = getTC1047temperature();if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){// Goto failsafe moderelayFailsafe();}else{// Transmitt node statustxMsg.Data.bytes[0] = boardTemperature & 0x00FF;txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;txMsg.Data.bytes[2] = relayStatus;txMsg.Data.bytes[3] = 0;txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_STATUS_RELAY<<TYPE_MASK_BITS )|(NODE_ID);bios->can_send( &txMsg );}}else if(msg->Data.bytes[0] == RELAY_CMD_RESET){// Return to normal operationfailsafe_flag = 0;}}}}/*----------------------------------------------------------------------------* Interrupt routines // FIXME ordna och testa tryckknappar/rotary encoder* -------------------------------------------------------------------------*/#if TWO_BUTTON_MODEISR( PCINT2_vect ){/** Auxiliary button pressed and released* Check time between press and release to eliminate bounces*/static uint32_t buttonTime[2];txMsg_Button.RemoteFlag = 0;txMsg_Button.ExtendedFlag = 1;if( (PIND & (1<<PD6)) == 0){/* Button pressed */buttonTime[0] = Timebase_CurrentTime();}else if( (PIND & (1<<PD6)) == 1){if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){/* No bounce, send message */txMsg_Button.Id = BUTTON_ID;txMsg_Button.DataLength = 1;txMsg_Button.Data.bytes[0] = BUTTON1;return;}else{/* Just bounces, ignore it */return;}}if( (PIND & (1<<PD7)) == 0){/* Button pressed */buttonTime[1] = Timebase_CurrentTime();}else if( (PIND & (1<<PD7)) == 1){if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){/* No bounce, send message */txMsg_Button.Id = BUTTON_ID;txMsg_Button.DataLength = 1;txMsg_Button.Data.bytes[0] = BUTTON2;return;}else{/* Just bounces, ignore it */return;}}}#endif/*-----------------------------------------------------------------------------* Main Program*---------------------------------------------------------------------------*/int main(void) {adcTemperatureInit();#if TWO_BUTTON_MODE#error two button mode not yet tested/** Initialize buttons* It is possible to use ie. sensors instead* but then change this*/// Set as input and enable pull-upDDRD &= ~( (1<<DDD6)|(1<<DDD7) );PORTD |= (1<<PD6)|(1<<PD7);// Enable IO-pin interruptPCICR |= (1<<PCIE1);// Unmask PD6 and PD7PCMSK2 |= (1<<PCINT22) | (1<<PCINT23);#endif// Control channel for relayDDRC |= (1<<DDC1);// Set up callback for CAN messages// bios->can_callback = &can_receive;txMsg.RemoteFlag = 0;txMsg.ExtendedFlag = 1;txMsg.DataLength = 4;sei();// Turn relay offrelayStatus = relayOff();txMsg.Id = 0x8000110UL; // FIXMEbios->can_send(&txMsg);uint32_t timeStamp = bios->timebase_get(), temp;// Main loopwhile (1) {temp = bios->timebase_get();if( temp - timeStamp >= STATUS_SEND_PERIOD ){timeStamp = temp;// Send relay status to CAN// boardTemperature = getTC1047temperature();// if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){// relayFailsafe();// }else{txMsg.Data.bytes[0] = timeStamp & 0x000000FF; //boardTemperature & 0x00FF;txMsg.Data.bytes[1] = (timeStamp & 0x0000FF00)>>8; //(boardTemperature & 0xFF00)>>8;txMsg.Data.bytes[2] = (timeStamp & 0x00FF0000)>>16; //relayStatus;txMsg.Data.bytes[3] = (timeStamp & 0xFF000000)>>24; //0;txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_STATUS_RELAY<<TYPE_MASK_BITS )|(NODE_ID);bios->can_send( &txMsg );// }}}return 0;}uint8_t relayOff(){// Turn off relayPORTC &= ~(1<<PC1);DDRC |= (1<<DDC1); // FIXMEreturn RELAY_OFF;}uint8_t relayOn(){// Turn on relayDDRC &= ~(1<<DDC1); // FIXMEPORTC |= (1<<PC1);return RELAY_ON;}void relayFailsafe(){uint32_t timeStamp = 0;relayStatus = relayOff();failsafe_flag = 1;while(1){if( !failsafe_flag ){// Return from failsafe modereturn;}if( bios->timebase_get() - timeStamp >= FAILSAFE_SEND_PERIOD ){timeStamp = bios->timebase_get();// Send relay status to CANboardTemperature = getTC1047temperature();txMsg.Data.bytes[0] = boardTemperature & 0x00FF;txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;txMsg.Data.bytes[2] = relayStatus;txMsg.Data.bytes[3] = FAILSAFE_MODE;txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_STATUS_RELAY<<TYPE_MASK_BITS )|(NODE_ID);bios->can_send( &txMsg );}}}