This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:projects:can_windscreen_wiper [2010/03/14 18:46] – mikk.leini | en:projects:can_windscreen_wiper [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== CAN windscreen wiper ====== | ||
| + | |||
| + | // | ||
| + | |||
| + | [{{ : | ||
| + | |||
| + | 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 ===== | ||
| + | |||
| + | <code 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 | ||
| + | #define CAN_ACTUATOR_MSG_ID | ||
| + | #define CAN_ACTUATOR_MSG_BOX | ||
| + | |||
| + | // | ||
| + | // | ||
| + | // 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, | ||
| + | |||
| + | // | ||
| + | // Next wiper mode of 3 modes. | ||
| + | // | ||
| + | g_ucMode = (g_ucMode + 1) % 3; | ||
| + | |||
| + | // | ||
| + | // Create message. | ||
| + | // | ||
| + | psCommandMsg.ulMsgID | ||
| + | psCommandMsg.ulFlags | ||
| + | psCommandMsg.ulMsgLen | ||
| + | psCommandMsg.pucMsgData = & | ||
| + | |||
| + | // | ||
| + | // Set message. | ||
| + | // | ||
| + | CANMessageSet(CAN0_BASE, | ||
| + | & | ||
| + | |||
| + | // | ||
| + | // Turn on the appropriate LED. | ||
| + | // | ||
| + | RGBLEDSetRGB((g_ucMode == 0 ? 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, | ||
| + | GPIOPinIntEnable(GPIO_PORTB_BASE, | ||
| + | IntEnable(INT_GPIOB); | ||
| + | |||
| + | // | ||
| + | // Configure CAN pins. | ||
| + | // | ||
| + | GPIOPinTypeCAN(GPIO_PORTD_BASE, | ||
| + | |||
| + | // | ||
| + | // Enable the CAN controller. | ||
| + | // | ||
| + | CANInit(CAN0_BASE); | ||
| + | CANBitRateSet(CAN0_BASE, | ||
| + | CANEnable(CAN0_BASE); | ||
| + | |||
| + | // | ||
| + | // Enable processor interrupts. | ||
| + | // | ||
| + | IntMasterEnable(); | ||
| + | |||
| + | // | ||
| + | // Loop forever. | ||
| + | // | ||
| + | while (1) | ||
| + | { | ||
| + | // | ||
| + | // Save power - turn off CPU. | ||
| + | // | ||
| + | SysCtlSleep(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== windscreen_wiper_actuator.c ===== | ||
| + | |||
| + | <code 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 | ||
| + | #define CAN_BITRATE | ||
| + | #define CAN_ACTUATOR_MSG_ID | ||
| + | #define CAN_ACTUATOR_MSG_BOX | ||
| + | #define CAN_ACTUATOR_MSG_BOX_FLAG | ||
| + | |||
| + | // | ||
| + | // | ||
| + | // Global variables. | ||
| + | // | ||
| + | // | ||
| + | signed long g_slWiperDirection = 1; | ||
| + | |||
| + | // | ||
| + | // | ||
| + | // The interrupt handler for the timer2 interrupt. | ||
| + | // | ||
| + | // | ||
| + | void Timer2IntHandler(void) | ||
| + | { | ||
| + | // | ||
| + | // Clear the timer interrupt. | ||
| + | // | ||
| + | TimerIntClear(TIMER2_BASE, | ||
| + | |||
| + | // | ||
| + | // Set servo position. | ||
| + | // | ||
| + | ServoSetPulseWidth(SERVO_INDEX, | ||
| + | |||
| + | // | ||
| + | // 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), | ||
| + | | ||
| + | | ||
| + | |||
| + | // | ||
| + | // Mode 0 ? | ||
| + | // | ||
| + | if (ucMode == 0) | ||
| + | { | ||
| + | // | ||
| + | // Disable wiper timer. | ||
| + | // | ||
| + | TimerDisable(TIMER2_BASE, | ||
| + | |||
| + | // | ||
| + | // Stop servo motor. | ||
| + | // | ||
| + | ServoSetPulseWidth(SERVO_INDEX, | ||
| + | } | ||
| + | // | ||
| + | // 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, | ||
| + | TimerEnable(TIMER2_BASE, | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | // 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, | ||
| + | { | ||
| + | // | ||
| + | // Get the message. | ||
| + | // | ||
| + | CANMessageGet(CAN0_BASE, | ||
| + | |||
| + | // | ||
| + | // 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 | | ||
| + | | ||
| + | |||
| + | // | ||
| + | // 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, | ||
| + | |||
| + | // | ||
| + | // Enable timer 2 interrupt. | ||
| + | // | ||
| + | TimerIntEnable(TIMER2_BASE, | ||
| + | IntEnable(INT_TIMER2A); | ||
| + | |||
| + | // | ||
| + | // Configure CAN pins. | ||
| + | // | ||
| + | GPIOPinTypeCAN(GPIO_PORTD_BASE, | ||
| + | |||
| + | // | ||
| + | // Enable the CAN controller. | ||
| + | // | ||
| + | CANInit(CAN0_BASE); | ||
| + | CANBitRateSet(CAN0_BASE, | ||
| + | CANEnable(CAN0_BASE); | ||
| + | |||
| + | // | ||
| + | // Enable CAN interrupts. | ||
| + | // | ||
| + | CANIntEnable(CAN0_BASE, | ||
| + | IntEnable(INT_CAN0); | ||
| + | |||
| + | // | ||
| + | // Create receive command message object. | ||
| + | // | ||
| + | psCommandMsg.ulMsgID | ||
| + | psCommandMsg.ulMsgIDMask = CAN_ACTUATOR_MSG_ID; | ||
| + | psCommandMsg.ulFlags | ||
| + | |||
| + | // | ||
| + | // Set message object. | ||
| + | // | ||
| + | CANMessageSet(CAN0_BASE, | ||
| + | |||
| + | // | ||
| + | // Enable processor interrupts. | ||
| + | // | ||
| + | IntMasterEnable(); | ||
| + | |||
| + | // | ||
| + | // Loop forever. | ||
| + | // | ||
| + | while (1) | ||
| + | { | ||
| + | // | ||
| + | // Save power - turn off CPU. | ||
| + | // | ||
| + | SysCtlSleep(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||