Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <math.h>
- #include "inc/hw_ints.h"
- #include "inc/hw_memmap.h"
- #include "inc/hw_types.h"
- #include "driverlib/adc.h"
- #include "driverlib/gpio.h"
- #include "driverlib/pin_map.h"
- #include "driverlib/sysctl.h"
- #include "driverlib/uart.h"
- #include "driverlib/interrupt.h"
- #include "utils/uartstdio.h"
- #include "driverlib/pwm.h"
- #include "driverlib/systick.c"
- #include "driverlib/systick.h"
- const int pwm_period = 1500;
- // Functions
- void sort(uint32_t sensor[60]);
- void InitConsole(void)
- {
- // Set the clock
- SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
- // UART
- // Enable GPIO port A which is used for UART0 pins.
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
- // Configure the pin muxing for UART0 functions on port A0 and A1.
- // Configure the pin muxing for UART1 functions on port B0 and B1.
- GPIOPinConfigure(GPIO_PA0_U0RX);
- GPIOPinConfigure(GPIO_PA1_U0TX);
- GPIOPinConfigure(GPIO_PB0_U1RX);
- GPIOPinConfigure(GPIO_PB1_U1TX);
- // Enable UART0 and UART1
- SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
- SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
- // Use the internal 16MHz oscillator as the UART clock source.
- UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
- UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
- // Select the alternate (UART) function for these pins.
- GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
- GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
- // Initialize the UART for console I/O.
- UARTStdioConfig(0, 9600, 16000000);
- UARTStdioConfig(1, 9600, 16000000);
- // PWM
- // Configure the PWM clock to match the system
- SysCtlPWMClockSet(SYSCTL_PWMDIV_64);
- // Enable peripherals used by the program
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); //Enable control of GPIO B
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Enable control of GPIO E
- // Enable peripherals used by the program
- SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); //Enable control of module 0
- SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //Enable control of module 1
- // Configure Pins as PWM
- GPIOPinConfigure(GPIO_PB6_M0PWM0); //Configure PB6 as PWM0
- GPIOPinConfigure(GPIO_PB7_M0PWM1); //Configure PB7 as PWM1 (inverted)
- GPIOPinConfigure(GPIO_PE4_M1PWM2); //Configure PE4 as PWM2
- GPIOPinConfigure(GPIO_PE5_M1PWM3); //Configure PE5 as PWM3 (inverted)
- GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6);
- GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
- // Configure PWM Options
- PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
- PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
- // Set the Period (expressed in clock ticks)
- PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, pwm_period);
- PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, pwm_period);
- // Set PWM duty
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, pwm_period);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwm_period);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, pwm_period);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, pwm_period);
- // Turn on the Output pins
- PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT, true);
- PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT | PWM_OUT_3_BIT, true);
- // Enable the PWM generator
- PWMGenEnable(PWM0_BASE, PWM_GEN_0);
- PWMGenEnable(PWM1_BASE, PWM_GEN_1);
- // Sensor
- // Enable ADC0 peripheral
- SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
- // Sensors use GPIO ports D and E
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
- // We want to use PD2, PD3, PE1 and PE2
- GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_2); //CH5
- GPIOPinTypeADC(GPIO_PORTD_BASE, GPIO_PIN_3); //CH4
- GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //CH2
- GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //CH1
- // Enable sample sequence 1
- ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
- // Configure the steps on the channels
- ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH1);
- ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2);
- ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH4);
- ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH5 | ADC_CTL_IE | ADC_CTL_END);
- // Enable sample sequence 1
- ADCSequenceEnable(ADC0_BASE, 1);
- // Clear the interrupt status flag before sampling.
- ADCIntClear(ADC0_BASE, 1);
- }
- // Define order type
- struct DrivingOrders
- {
- uint32_t number[2];
- uint32_t direction;
- uint32_t angle[3];
- uint32_t distance[3];
- };
- // Define order and create array of orders.
- typedef struct DrivingOrders order;
- order o[30];
- // Function to delay
- void delayMS(int ms)
- {
- SysCtlDelay((SysCtlClockGet() / (3 * 1000 )) * ms);
- }
- // Function to receive order
- int GetOrders(order *o, int num)
- {
- int i = 0;
- for(i = 0; i < num; i++)
- {
- // If not the first value received -> read white space
- if (i > 0)
- {
- UARTCharGet(UART1_BASE);
- }
- // Read driving order number
- o[i].number[0] = UARTCharGet(UART1_BASE);
- o[i].number[1] = UARTCharGet(UART1_BASE);
- // Read white space
- UARTCharGet(UART1_BASE);
- // Read direction H/V/D/R
- o[i].direction = UARTCharGet(UART1_BASE);
- // Read angle 000/045/090/135/180
- o[i].angle[0] = UARTCharGet(UART1_BASE);
- o[i].angle[1] = UARTCharGet(UART1_BASE);
- o[i].angle[2] = UARTCharGet(UART1_BASE);
- // Read white space
- UARTCharGet(UART1_BASE);
- // Read distance
- o[i].distance[0] = UARTCharGet(UART1_BASE);
- o[i].distance[1] = UARTCharGet(UART1_BASE);
- o[i].distance[2] = UARTCharGet(UART1_BASE);
- }
- // Return number of orders
- return num;
- }
- // Function to print order via USB
- void PrintOrder(order o[0], int n)
- {
- int i = 0;
- char temp = ' ';
- while(i < n)
- {
- // Number
- UARTCharPut(UART0_BASE, o[i].number[0]);
- UARTCharPut(UART0_BASE, o[i].number[1]);
- UARTCharPut(UART0_BASE, temp);
- // Direction
- UARTCharPut(UART0_BASE, o[i].direction);
- // Angle
- UARTCharPut(UART0_BASE, o[i].angle[0]);
- UARTCharPut(UART0_BASE, o[i].angle[1]);
- UARTCharPut(UART0_BASE, o[i].angle[2]);
- UARTCharPut(UART0_BASE, temp);
- // Distance
- UARTCharPut(UART0_BASE, o[i].distance[0]);
- UARTCharPut(UART0_BASE, o[i].distance[1]);
- UARTCharPut(UART0_BASE, o[i].distance[2]);
- UARTCharPut(UART0_BASE, temp);
- i++;
- }
- }
- // Function to stop the vehicle
- void stop()
- {
- uint32_t pwmNow = pwm_period;
- PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT|PWM_OUT_1_BIT), false);
- PWMOutputState(PWM1_BASE, (PWM_OUT_2_BIT|PWM_OUT_3_BIT), false);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, pwmNow);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, pwmNow);
- }
- // Function to receive data from sensors
- uint32_t IRsensor(int loop)
- {
- int i=0;
- const uint16_t n = 10;
- uint32_t sum;
- uint32_t ADCvalue[4];
- uint32_t sensor[10];
- uint32_t dda;
- while(i < n - 1)
- {
- // Trigger the ADC conversion.
- ADCProcessorTrigger(ADC0_BASE, 1);
- // Wait until the sample seq is completed
- while(!ADCIntStatus(ADC0_BASE, 1, false))
- {
- }
- // Read ADC Value. Store from all sensors (ADCValue)
- ADCSequenceDataGet(ADC0_BASE, 1, ADCvalue);
- // Store the value from the sensor in value
- sensor[i] = ADCvalue[loop - 1];
- delayMS(3);
- i++;
- }
- // Reset the variables
- sum=0;
- i=4;
- while(i < 7)
- {
- sum+=sensor[i];
- i++;
- }
- sum = sum/3;
- // Use different algorithms depending on sensor
- // Sensor 1, 4 - 40 cm
- if(loop == 1)
- {
- dda = 36.68*exp(-0.008286*sum)+41.56*exp(-0.001496*sum);
- if(dda > 30)
- dda = 30;
- }
- // Sensor 2, 4 - 40 cm
- else if (loop == 2)
- {
- dda = 56.79*exp(-0.005785*sum)+40.74*exp(-0.001389*sum);
- if(dda > 30)
- dda = 30;
- }
- // Sensor 3, 8 - 80 cm
- else if (loop == 3)
- {
- dda = 751.5*exp(-0.005364*sum)+53.89*exp(-0.0006045*sum);
- if(dda > 60)
- dda = 60;
- }
- // Sensor 4, 8 - 80 cm
- else if (loop == 4)
- {
- dda = 479.2*exp(-0.004304*sum)+51.75*exp(-0.0005874*sum);
- if(dda > 60)
- dda = 60;
- }
- return dda;
- }
- // Function to drive the vehicle
- int drive(uint32_t m, uint32_t dm)
- {
- m = m - 48;
- dm = dm - 48;
- uint32_t pwmNow = pwm_period;
- int i = 1;
- uint32_t sensor[4];
- int loop = 0;
- int error = 0;
- loop = 2*(m*10 + dm);
- // Turn on the "forward" pins and off the "backward" pins
- PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false);
- PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT, false);
- PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
- PWMOutputState(PWM1_BASE, PWM_OUT_3_BIT, true);
- // Set the pulse width
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, pwmNow - 100);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, pwmNow);
- while(i <= loop)
- {
- // Collect data from sensors
- sensor[0] = IRsensor(1); // Sensor 1 DH
- sensor[1] = IRsensor(2); // Sensor 2 DV
- sensor[2] = IRsensor(3); // Sensor 3 H
- sensor[3] = IRsensor(4); // Sensor 4 V
- // If the sensor is 10 cm from an obstacle -> stop
- if(sensor[0] <= 10) // DH
- {
- stop();
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- UARTprintf("Unable to complete order, obstacle %d cm to the front-right.\n", sensor[0]);
- i = loop+1;
- error = 1;
- break;
- }
- // If the sensor is 10 cm from an obstacle -> stop
- else if(sensor[1] <= 10) // DV
- {
- stop();
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- UARTprintf("Unable to complete order, obstacle %d cm to the front-left.\n", sensor[1]);
- i = loop+1;
- error = 1;
- break;
- }
- // If stop-command -> stop
- if(UARTCharGetNonBlocking(UART1_BASE) == 'S')
- {
- stop();
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- i = loop+1;
- error = 1;
- break;
- }
- // Display the data
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- delayMS(25);
- i++;
- }
- stop();
- delayMS(1000); // Delay 1 second
- return error;
- }
- int reverse(uint32_t m, uint32_t dm)
- {
- m = m - 48;
- dm = dm - 48;
- uint32_t pwmNow = pwm_period;
- int i = 1;
- uint32_t sensor[4];
- int loop = 0;
- int error = 0;
- loop = 2*(m*10 + dm);
- // Turn on the "backward" pins and off the "forward" pins
- PWMOutputState(PWM1_BASE, PWM_OUT_3_BIT, false);
- PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, false);
- PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
- PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT, true);
- // Set the pulse width
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, pwmNow);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmNow - 47);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, pwmNow);
- while(i <= loop)
- {
- // Collect sensor data
- sensor[0] = IRsensor(1); // Sensor 1 DH
- sensor[1] = IRsensor(2); // Sensor 2 DV
- sensor[2] = IRsensor(3); // Sensor 3 H
- sensor[3] = IRsensor(4); // Sensor 4 V
- // If the sensor is 10 cm from an obstacle -> stop
- if(sensor[0] <= 10) // DH
- {
- stop();
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- UARTprintf("Unable to complete order, obstacle %d cm to the front-right.\n", sensor[0]);
- i = loop+1;
- error = 1;
- break;
- }
- // If the sensor is 10 cm from an obstacle -> stop
- else if(sensor[1] <= 10) // DV
- {
- stop();
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- UARTprintf("Unable to complete order, obstacle %d cm to the front-left.\n", sensor[1]);
- i = loop+1;
- error = 1;
- break;
- }
- // If stop-command -> stop
- if(UARTCharGetNonBlocking(UART1_BASE) == 'S') // Kรถra fram tills vi tar emot ett S (stop)
- {
- stop();
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- i = loop+1;
- error = 1;
- break;
- }
- // Display the data
- UARTprintf("V%d ", sensor[3]);
- UARTprintf("DV%d ", sensor[1]);
- UARTprintf("DH%d ", sensor[0]);
- UARTprintf("H%d\n", sensor[2]);
- delayMS(24);
- i++;
- }
- stop();
- delayMS(1000); // Delay 1 second
- return error;
- }
- // Function to turn left
- void turn_left(int n)
- {
- n = n - 48;
- uint32_t pwmNow = pwm_period - 500;
- // Turn off the back-pin for the right side and front-pin for the left side
- PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT, false);
- PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, false);
- // Turn on the back-pin for the left side and front-pin for the right side
- PWMOutputState(PWM1_BASE, PWM_OUT_3_BIT, true);
- PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
- // Set the pulse width
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, pwmNow);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmNow - 47);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, pwmNow);
- // If 45 degrees
- if(n == 4)
- delayMS(575);
- // If 90 degrees
- else if (n == 9)
- delayMS(1115);
- // If 135 degrees
- else if (n == 3)
- delayMS(1650);
- // If 180 degrees
- else if (n == 8)
- delayMS(2170);
- stop();
- delayMS(250);
- }
- // Function to turn right
- void turn_right(int n)
- {
- n = n - 48;
- uint32_t pwmNow = pwm_period - 500;
- // Turn on the front-pin for the right side and the back-pin for the left side
- PWMOutputState(PWM1_BASE, PWM_OUT_3_BIT, false);
- PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, false);
- // Turn on the front-pin for the left side and the back-pin for the right side
- PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT, true);
- PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true);
- // Set the pulse width
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, pwmNow - 100);
- PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, pwmNow);
- PWMPulseWidthSet(PWM1_BASE, PWM_OUT_3, pwmNow);
- // If 45 degrees
- if(n == 4)
- delayMS(590);
- // If 90 degrees
- else if (n == 9)
- delayMS(1145);
- // If 135 degrees
- else if (n == 3)
- delayMS(1655);
- // If 180 degrees
- else if (n == 8)
- delayMS(2200);
- stop();
- delayMS(250);
- }
- int main(void)
- {
- // Variables
- int command;
- int orders = 0;
- int orderT = 0, orderE;
- int i = 0;
- int error = 0;
- uint32_t sensor1 = 0, sensor2 = 0, sensor3 = 0, sensor4 = 0;
- // Initialize
- InitConsole();
- // Create different states for the state machine
- enum states
- {
- wait,
- mapping,
- transport
- };
- // Set default state to wait
- enum states state = wait;
- while(1)
- {
- switch(state)
- {
- case wait:
- stop();
- UARTprintf("Which state? \n");
- command = UARTCharGet(UART1_BASE);
- // If 'K'
- if(command == 75)
- {
- state = mapping;
- }
- // If 'T'
- else if (command == 84)
- {
- state = transport;
- }
- else
- {
- UARTprintf("This state does not exist... \n");
- }
- break;
- case mapping:
- // Collect data from sensors
- sensor1 = IRsensor(1);
- sensor2 = IRsensor(2);
- sensor3 = IRsensor(3);
- sensor4 = IRsensor(4);
- // Display the data
- UARTprintf("V%d ", sensor4);
- UARTprintf("DV%d ", sensor2);
- UARTprintf("DH%d ", sensor1);
- UARTprintf("H%d\n", sensor3);
- while(1) // Infinity loop until stop-command
- {
- GetOrders(o, 1);
- PrintOrder(&o[0], 1);
- // Perform the order
- if(o[0].direction == 'D')
- {
- drive(o[0].distance[0], o[0].distance[1]);
- }
- else if(o[0].direction == 'R')
- {
- reverse(o[0].distance[0], o[0].distance[1]);
- }
- else if(o[0].direction == 'V')
- {
- turn_left(o[0].angle[1]);
- drive(o[0].distance[0], o[0].distance[1]);
- }
- else if(o[0].direction == 'H')
- {
- turn_right(o[0].angle[1]);
- drive(o[0].distance[0], o[0].distance[1]);
- }
- else if(o[0].number[0] == 'S')
- {
- break;
- }
- stop();
- }
- state = wait;
- break;
- case transport:
- UARTprintf("How many transport orders? \n");
- orderT = UARTCharGet(UART1_BASE);
- orderE = UARTCharGet(UART1_BASE);
- orders = (orderT-48)*10 + (orderE-48);
- command = GetOrders(o, orders);
- // Collect data from sensors
- sensor1 = IRsensor(1);
- sensor2 = IRsensor(2);
- sensor3 = IRsensor(3);
- sensor4 = IRsensor(4);
- // Display the data
- UARTprintf("V%d ", sensor4);
- UARTprintf("DV%d ", sensor2);
- UARTprintf("DH%d ", sensor1);
- UARTprintf("H%d\n", sensor3);
- for(i = 0; i < command; i++)
- {
- // Perform the driving order
- if(o[i].direction == 'D')
- {
- error = drive(o[i].distance[0], o[i].distance[1]);
- }
- else if(o[i].direction == 'R')
- {
- error = reverse(o[i].distance[0], o[i].distance[1]);
- }
- else if(o[i].direction == 'V')
- {
- turn_left(o[i].angle[1]);
- error = drive(o[i].distance[0], o[i].distance[1]);
- }
- else if(o[i].direction == 'H')
- {
- turn_right(o[i].angle[1]);
- error = drive(o[i].distance[0], o[i].distance[1]);
- }
- if(error == 1)
- {
- i = command;
- break;
- }
- stop();
- }
- if(error == 1)
- state = transport;
- else
- state = wait;
- break;
- }
- SysCtlDelay(SysCtlClockGet() / 12);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement