Table of Contents

CAN windscreen wiper

Requirements: [HW] 2 x Controller, [HW] Servo-motor

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:

windscreen_wiper_control.c

//*****************************************************************************
//
// Windscreen wiper control
//
// Program is entirely interrupts based.
//
// Copyright (c) 2009 TUT Department of Mechatronics
//
//*****************************************************************************
 
#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/interrupt.h>
#include <driverlib/gpio.h>
#include <driverlib/timer.h>
#include <driverlib/can.h>
#include <drivers/general.h>
#include <drivers/rgb_led.h>
 
//*****************************************************************************
//
// 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 <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/interrupt.h>
#include <driverlib/gpio.h>
#include <driverlib/timer.h>
#include <driverlib/can.h>
#include <drivers/general.h>
#include <drivers/rgb_led.h>
#include <drivers/servo_motor.h>
 
//*****************************************************************************
//
// 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();
	}
}