====== CAN windscreen wiper ====== //Requirements: [HW] 2 x [[en:hardware:arm-can:controller]], [HW] Servo-motor// [{{ :images:projects:can_windscreen_wiper:windscreen_wiper.gif|Windscreen wiper in different modes}}] This project demonstrates how to use CAN interface to transfer commands from one device to other. Two ARM-CAN contollers are need of which one acts as a lever on the steering wheel of a car and another one as a windscreen wiper controller. When buttons is pressed on lever controller, next wiping mode is selected and wiper is notified. Servo-motor is used for simulating the wiper. There are three modes: * Stop mode. Wiper is not moving. Red LED's are on. * Slow mode. Wiper is moving slowly from side to side. Green LED's are on. * Fast mode. Wiper is moving rapidly from side to side. Blue LED's are on. ~~CL~~ ===== windscreen_wiper_control.c ===== //***************************************************************************** // // Windscreen wiper control // // Program is entirely interrupts based. // // Copyright (c) 2009 TUT Department of Mechatronics // //***************************************************************************** #include #include #include #include #include #include #include #include #include #include //***************************************************************************** // // Configuration. // //***************************************************************************** #define CAN_BITRATE 250000 #define CAN_ACTUATOR_MSG_ID 0x01 #define CAN_ACTUATOR_MSG_BOX 1 //***************************************************************************** // // Global variables. // //***************************************************************************** unsigned char g_ucMode = 0; //***************************************************************************** // // The interrupt handler for the port B interrupt. // //***************************************************************************** void PortBIntHandler(void) { tCANMsgObject psCommandMsg; // // Clear the port interrupt. // GPIOPinIntClear(GPIO_PORTB_BASE, GPIO_PIN_7); // // Next wiper mode of 3 modes. // g_ucMode = (g_ucMode + 1) % 3; // // Create message. // psCommandMsg.ulMsgID = CAN_ACTUATOR_MSG_ID; psCommandMsg.ulFlags = MSG_OBJ_NO_FLAGS; psCommandMsg.ulMsgLen = 1; psCommandMsg.pucMsgData = &g_ucMode; // // Set message. // CANMessageSet(CAN0_BASE, CAN_ACTUATOR_MSG_BOX, &psCommandMsg, MSG_OBJ_TYPE_TX); // // Turn on the appropriate LED. // RGBLEDSetRGB((g_ucMode == 0 ? 255 : 0), (g_ucMode == 1 ? 255 : 0), (g_ucMode == 2 ? 255 : 0)); } //***************************************************************************** // // Main function. // //***************************************************************************** int main(void) { // // Set the clocking to run from the PLL at 50MHz // SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ); // // Enable peripherals. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Enable the peripherals that should continue to run when the processor // is sleeping. // SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOB); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_CAN0); // // Drivers configuring. // DeviceConfigure(); RGBLEDConfigure(); // // Configure button to generate interrupt on press. // GPIOIntTypeSet(GPIO_PORTB_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE); GPIOPinIntEnable(GPIO_PORTB_BASE, GPIO_PIN_7); IntEnable(INT_GPIOB); // // Configure CAN pins. // GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Enable the CAN controller. // CANInit(CAN0_BASE); CANBitRateSet(CAN0_BASE, SysCtlClockGet(), CAN_BITRATE); CANEnable(CAN0_BASE); // // Enable processor interrupts. // IntMasterEnable(); // // Loop forever. // while (1) { // // Save power - turn off CPU. // SysCtlSleep(); } } ===== windscreen_wiper_actuator.c ===== //***************************************************************************** // // Windscreen wiper actuator // // Program is entirely interrupts based. // // Copyright (c) 2009 TUT Department of Mechatronics // //***************************************************************************** #include #include #include #include #include #include #include #include #include #include #include //***************************************************************************** // // Configuration. // //***************************************************************************** #define SERVO_INDEX 0 #define CAN_BITRATE 250000 #define CAN_ACTUATOR_MSG_ID 0x01 #define CAN_ACTUATOR_MSG_BOX 1 #define CAN_ACTUATOR_MSG_BOX_FLAG (1 << (CAN_ACTUATOR_MSG_BOX - 1)) //***************************************************************************** // // Global variables. // //***************************************************************************** signed long g_slWiperDirection = 1; //***************************************************************************** // // The interrupt handler for the timer2 interrupt. // //***************************************************************************** void Timer2IntHandler(void) { // // Clear the timer interrupt. // TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT); // // Set servo position. // ServoSetPulseWidth(SERVO_INDEX, 100 * g_slWiperDirection); // // Reverse wiper direction. // g_slWiperDirection = -g_slWiperDirection; } //***************************************************************************** // // Wiper mode setting. // //***************************************************************************** void WiperModeSet(unsigned char ucMode) { unsigned long ulPeriod = 0; // // Turn on the appropriate LED. // RGBLEDSetRGB((ucMode == 0 ? 255 : 0), (ucMode == 1 ? 255 : 0), (ucMode == 2 ? 255 : 0)); // // Mode 0 ? // if (ucMode == 0) { // // Disable wiper timer. // TimerDisable(TIMER2_BASE, TIMER_A); // // Stop servo motor. // ServoSetPulseWidth(SERVO_INDEX, 0); } // // Mode 1 or 2 ? // else if (ucMode <= 2) { // // Set period according to the mode. // switch (ucMode) { case 1: ulPeriod = SysCtlClockGet() * 2; // 2 s break; case 2: ulPeriod = SysCtlClockGet() / 2; // 500 ms break; } // // Configure periodic timer to generate interrupt. // TimerLoadSet(TIMER2_BASE, TIMER_A, ulPeriod); TimerEnable(TIMER2_BASE, TIMER_A); } } //***************************************************************************** // // The interrupt handler for the CAN interrupt. // //***************************************************************************** void CAN0IntHandler(void) { tCANMsgObject psCommandMsg; unsigned char pucRxData[8]; unsigned char ucMode = 0; // // Set pointer to data. // psCommandMsg.pucMsgData = pucRxData; // // New CAN message received ? // if (CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT) & CAN_ACTUATOR_MSG_BOX_FLAG) { // // Get the message. // CANMessageGet(CAN0_BASE, CAN_ACTUATOR_MSG_BOX_FLAG, &psCommandMsg, true); // // Check message length. // if (psCommandMsg.ulMsgLen == 1) { // // Get mode from data. // ucMode = *psCommandMsg.pucMsgData; // // Set wiper mode. // WiperModeSet(ucMode); } } } //***************************************************************************** // // Main function. // //***************************************************************************** int main(void) { tCANMsgObject psCommandMsg; // // Set the clocking to run from the PLL at 50MHz // SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ); // // Enable peripherals. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Enable the peripherals that should continue to run when the processor // is sleeping. // SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOB); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOC); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER0); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER2); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_CAN0); // // Drivers configuring. // DeviceConfigure(); RGBLEDConfigure(); ServoConfigure(SERVO_INDEX); // // Configure timer 2 as periodic wiper timer. // TimerConfigure(TIMER2_BASE, TIMER_CFG_32_BIT_PER); // // Enable timer 2 interrupt. // TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT); IntEnable(INT_TIMER2A); // // Configure CAN pins. // GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Enable the CAN controller. // CANInit(CAN0_BASE); CANBitRateSet(CAN0_BASE, SysCtlClockGet(), CAN_BITRATE); CANEnable(CAN0_BASE); // // Enable CAN interrupts. // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_STATUS); IntEnable(INT_CAN0); // // Create receive command message object. // psCommandMsg.ulMsgID = CAN_ACTUATOR_MSG_ID; psCommandMsg.ulMsgIDMask = CAN_ACTUATOR_MSG_ID; psCommandMsg.ulFlags = MSG_OBJ_RX_INT_ENABLE; // // Set message object. // CANMessageSet(CAN0_BASE, CAN_ACTUATOR_MSG_BOX, &psCommandMsg, MSG_OBJ_TYPE_RX); // // Enable processor interrupts. // IntMasterEnable(); // // Loop forever. // while (1) { // // Save power - turn off CPU. // SysCtlSleep(); } }