====== 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();
}
}