====== 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}}]
Dieses Projekt demonstriert wie man das CAN Interface nutzt um Befehle von einem Gerät zum anderen zu senden. Zwei ARM-CAN Controller werden benötigt, wovon einer als Schalter am Lenkrand fungiert, und der andere als Scheibenwischercontroller. Wenn der Knopf am Schaltercontroller gedrückt wird, wird der nächste Wischmodus ausgewählt und der Wischer benachrichtigt. Der Servomotor wird als Simulation für den Wischer genutzt.
Es gibt drei Modi:
* Stop Modus. Wischer bewegt sich nicht. Rote LED's sind an.
* Langsamer Modus. Wischer bewegt sich langsam von Seite zu Seite. Grüne LED's sind an.
* Schneller Modus. Wischer bewegt sich schnell von Seite zu Seite. Blaue LED's sind an.
~~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();
}
}