//#############################################################################
// FILE: FinalProjectStarter_main.c
//
// TITLE: Final Project Starter
// Code written by ECC5 JEY2 LIANNAM2 COGGANB2 initials - (EC JY LM CB) for comments
//#############################################################################
// Included Files
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include "F28x_Project.h"
#include "F2837xD_SWPrioritizedIsrLevels.h"
#include "driverlib.h"
#include "device.h"
#include "F28379dSerial.h"
#include "song.h"
#include "dsp.h"
#include "fpu32/fpu_rfft.h"
#include "xy.h"
#include "MatrixMath.h"
#include "SE423Lib.h"
#include "OptiTrack.h"
#define PI 3.1415926535897932384626433832795
#define TWOPI 6.283185307179586476925286766559
#define HALFPI 1.5707963267948966192313216916398
// The Launchpad's CPU Frequency set to 200 you should not change this value
#define LAUNCHPAD_CPU_FREQUENCY 200
// ----- code for CAN start here -----
#include "F28379dCAN.h"
//#define TX_MSG_DATA_LENGTH 4
//#define TX_MSG_OBJ_ID 0 //transmit
#define RX_MSG_DATA_LENGTH 8
#define RX_MSG_OBJ_ID_1 1 //measurement from sensor 1
#define RX_MSG_OBJ_ID_2 2 //measurement from sensor 2
#define RX_MSG_OBJ_ID_3 3 //quality from sensor 1
#define RX_MSG_OBJ_ID_4 4 //quality from sensor 2
// ----- code for CAN end here -----
// Interrupt Service Routines predefinition
__interrupt void cpu_timer0_isr(void);
__interrupt void cpu_timer1_isr(void);
__interrupt void cpu_timer2_isr(void);
__interrupt void SWI1_HighestPriority(void);
__interrupt void SWI2_MiddlePriority(void);
__interrupt void SWI3_LowestPriority(void);
__interrupt void ADCC_ISR(void);
__interrupt void SPIB_isr(void);
// ----- code for CAN start here -----
__interrupt void can_isr(void);
// ----- code for CAN end here -----
void setF28027EPWM1A(float controleffort);
int16_t EPwm1A_F28027 = 1500;
void setF28027EPWM2A(float controleffort);
int16_t EPwm2A_F28027 = 1500;
// ----- code for CAN start here -----
// volatile uint32_t txMsgCount = 0;
// extern uint16_t txMsgData[4];
volatile uint32_t rxMsgCount_1 = 0;
volatile uint32_t rxMsgCount_2 = 0;
extern uint16_t rxMsgData[8];
uint32_t dis_raw_1[2];
uint32_t dis_raw_2[2];
uint32_t dis_1 = 0;
uint32_t dis_2 = 0;
uint32_t quality_raw_1[4];
uint32_t quality_raw_2[4];
float quality_1 = 0.0;
float quality_2 = 0.0;
uint32_t lightlevel_raw_1[4];
uint32_t lightlevel_raw_2[4];
float lightlevel_1 = 0.0;
float lightlevel_2 = 0.0;
uint32_t measure_status_1 = 0;
uint32_t measure_status_2 = 0;
volatile uint32_t errorFlag = 0;
// ----- code for CAN end here -----
uint32_t numTimer0calls = 0;
uint16_t UARTPrint = 0;
float printLV1 = 0;
float printLV2 = 0;
float printLinux1 = 0;
float printLinux2 = 0;
uint16_t LADARi = 0;
char G_command[] = "G04472503\n"; //command for getting distance -120 to 120 degree
uint16_t G_len = 11; //length of command
xy ladar_pts[228]; //xy data
float LADARleftfront = 0;
float LADARrightfront = 0;
float LADARfront = 0;
float LADARtemp_x = 0;
float LADARtemp_y = 0;
extern datapts ladar_data[228];
extern uint16_t newLinuxCommands;
extern float LinuxCommands[CMDNUM_FROM_FLOATS];
extern uint16_t NewLVData;
extern float fromLVvalues[LVNUM_TOFROM_FLOATS];
extern LVSendFloats_t DataToLabView;
extern char LVsenddata[LVNUM_TOFROM_FLOATS*4+2];
extern uint16_t LADARpingpong;
extern uint16_t NewCAMDataThreshold1; // Flag new data
extern float fromCAMvaluesThreshold1[CAMNUM_FROM_FLOATS];
extern uint16_t NewCAMDataThreshold2; // Flag new data
extern float fromCAMvaluesThreshold2[CAMNUM_FROM_FLOATS];
extern uint16_t NewCAMDataAprilTag1; // Flag new data
extern float fromCAMvaluesAprilTag1[CAMNUM_FROM_FLOATS];
// JY LM CB list of global variables for final project
float tagid = 0;
float tagx = 0;
float tagy = 0;
float tagz = 0;
float tagthetax = 0;
float tagthetay = 0;
float tagthetaz = 0;
int32_t numtag = 0;
int32_t AprilTagState = 10;
float KpAprilTag = -1.0;
float AprilTagSetPoint = 0;
int32_t AprilTagCount = 0;
float MaxAreaThreshold1 = 0;
float MaxColThreshold1 = 0;
float MaxRowThreshold1 = 0;
float NextLargestAreaThreshold1 = 0;
float NextLargestColThreshold1 = 0;
float NextLargestRowThreshold1 = 0;
float NextNextLargestAreaThreshold1 = 0;
float NextNextLargestColThreshold1 = 0;
float NextNextLargestRowThreshold1 = 0;
float MaxAreaThreshold2 = 0;
float MaxColThreshold2 = 0;
float MaxRowThreshold2 = 0;
float NextLargestAreaThreshold2 = 0;
float NextLargestColThreshold2 = 0;
float NextLargestRowThreshold2 = 0;
float NextNextLargestAreaThreshold2 = 0;
float NextNextLargestColThreshold2 = 0;
float NextNextLargestRowThreshold2 = 0;
uint32_t numThres1 = 0;
uint32_t numThres2 = 0;
pose ROBOTps = {0,0,0}; //robot position
pose LADARps = {3.5/12.0,0,1}; // 3.5/12 for front mounting, theta is not used in this current code
float LADARxoffset = 0;
float LADARyoffset = 0;
uint32_t timecount = 0;
int16_t RobotState = 0;
int16_t checkfronttally = 0;
int32_t WallFollowtime = 0;
// FINAL PROJECT 4 CORNERS + home
#define NUMWAYPOINTS 6 // LAB7: ADDED 2 POINTS = 10,
#define NUMWAYPOINTS1 11 // LAB7: ADDED 2 POINTS = 10,
pose scandest[NUMWAYPOINTS1]; // array of waypoints for the robot
uint16_t statePos = 0;
uint16_t finalStatePos = 0;
pose robotdest[NUMWAYPOINTS]; // array of waypoints for the robot
uint16_t i = 0;//for loop
uint16_t right_wall_follow_state = 2; // right follow
float Kp_front_wall = -2.0;
float front_turn_velocity = 0.2;
float left_turn_Stop_threshold = 3.5;
float Kp_right_wal = -4.0;
float ref_right_wall = 1.1;
float foward_velocity = 1.0;
float left_turn_Start_threshold = 1.3;
float turn_saturation = 2.5;
float x_pred[3][1] = {{0},{0},{0}}; // predicted state
//more kalman vars
float B[3][2] = {{1,0},{1,0},{0,1}}; // control input model
float u[2][1] = {{0},{0}}; // control input in terms of velocity and angular velocity
float Bu[3][1] = {{0},{0},{0}}; // matrix multiplication of B and u
float z[3][1]; // state measurement
float eye3[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; // 3x3 identity matrix
float K[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; // optimal Kalman gain
#define ProcUncert 0.0001
#define CovScalar 10
float Q[3][3] = {{ProcUncert,0,ProcUncert/CovScalar},
{0,ProcUncert,ProcUncert/CovScalar},
{ProcUncert/CovScalar,ProcUncert/CovScalar,ProcUncert}}; // process noise (covariance of encoders and gyro)
#define MeasUncert 1
float R[3][3] = {{MeasUncert,0,MeasUncert/CovScalar},
{0,MeasUncert,MeasUncert/CovScalar},
{MeasUncert/CovScalar,MeasUncert/CovScalar,MeasUncert}}; // measurement noise (covariance of OptiTrack Motion Capture measurement)
float S[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; // innovation covariance
float S_inv[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; // innovation covariance matrix inverse
float P_pred[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; // predicted covariance (measure of uncertainty for current position)
float temp_3x3[3][3]; // intermediate storage
float temp_3x1[3][1]; // intermediate storage
float ytilde[3][1]; // difference between predictions
// Optitrack Variables
int32_t OptiNumUpdatesProcessed = 0;
pose OPTITRACKps;
extern uint16_t new_optitrack;
extern float Optitrackdata[OPTITRACKDATASIZE];
int16_t newOPTITRACKpose=0;
int16_t adcc2result = 0;
int16_t adcc3result = 0;
int16_t adcc4result = 0;
int16_t adcc5result = 0;
float adcC2Volt = 0.0;
float adcC3Volt = 0.0;
float adcC4Volt = 0.0;
float adcC5Volt = 0.0;
int32_t numADCCcalls = 0;
float LeftWheel = 0;
float RightWheel = 0;
float LeftWheel_1 = 0;
float RightWheel_1 = 0;
float LeftVel = 0;
float RightVel = 0;
float uLeft = 0;
float uRight = 0;
float HandValue = 0;
float vref = 0;
float turn = 0;
float gyro9250_drift = 0;
float gyro9250_angle = 0;
float old_gyro9250 = 0;
float gyroLPR510_angle = 0;
float gyroLPR510_offset = 0;
float gyroLPR510_drift = 0;
float old_gyroLPR510 = 0;
float gyro9250_radians = 0;
float gyroLPR510_radians = 0;
int16_t readdata[25];
int16_t IMU_data[9];
float accelx = 0;
float accely = 0;
float accelz = 0;
float gyrox = 0;
float gyroy = 0;
float gyroz = 0;
// Needed global Variables
float accelx_offset = 0;
float accely_offset = 0;
float accelz_offset = 0;
float gyrox_offset = 0;
float gyroy_offset = 0;
float gyroz_offset = 0;
int16_t calibration_state = 0;
int32_t calibration_count = 0;
int16_t doneCal = 0;
#define MPU9250 1
#define DAN28027 2
int16_t CurrentChip = MPU9250;
int16_t DAN28027Garbage = 0;
int16_t dan28027adc1 = 0;
int16_t dan28027adc2 = 0;
uint16_t MPU9250ignoreCNT = 0; //This is ignoring the first few interrupts if ADCC_ISR and start sending to IMU after these first few interrupts.
// EC JY LM CB LAB 7 CODE
float RCangle1 = 70;
float RCangle2 = 70;
float RCangle3 = 70;
float RCangle4 = 70;
float RCangle5 = 70;
float x = 0; // temp
float ePDist = 0;
float eGDist = 0;
float kpvision = -0.05;
float colcentroid = 0;
int count22 = 0;
int count24 = 0;
int count26 = 0;
// EC JY LM CB FINAL PROJECT INT VARIABLES
int count21 = 0;
int count31 = 0;
int count2 = 0;
int count0 = 0;
int count1 = 0;
int count51 = 0;
int ballcount = 0; //used to end search early and deposit balls
int funny_ball_flag = 0; //used to represent illegal (funny) balls
float coffset = 22; //used to center the robot on ball collection better
// EC JY LM CB FINAL PROJECT LabView remote control variables
float user_vref = 0;
float user_turn = 0;
int user_drop = 0;
int funny_drop_flag = 0;
pose goal_dest[3];
// camera is epwm5a
//door is gpio5 - epwm5b
//sorter is gpio7 - epwm6a
//Final Lab Problematic Functions
//The Orient function takes as input the variables used to maneuver the robot and a flag that specifies when the ball dropoff process should run.
//The other inputs to this function represent data used to autonomously orient the robot closer to an AprilTag (WIP)
//The output of this function is a boolean that represents when orient should be running or when it should be skipped in favor of ball dropoff.
static inline int Orient(float tagthetaz, float LADARfront, float LADARrightfront, float LADARleftfront, float* turn, float* vref, float user_turn, float user_vref, int user_drop, int* funny_drop_flag) {
static int count = 0;
static int local_drop = 0;
// *vref = 0;
//at this point, it should be where it "saw" the April Tag, we need to get closer
// if (count < 3000) {
// if (fabs(tagthetaz) > 3.0) {
// //negative values imply turn to left, positive imply turn right
// *turn = (tagthetaz - 180 > 0) ? -0.5 : 0.5;
// }
// else *turn = (count < 500) ? -0.5 : 0.5; //looking left and right
// }
// else {
// *vref = 0.4;
// if(LADARfront < 1.2 || LADARrightfront < 1.2 || LADARleftfront < 1.2) {
// *vref = 0;
// count = 0;
// return 0;
// }
// }
// REMOTE CONTROL
*turn = user_turn;
*vref = user_vref;
if (user_drop != local_drop) {local_drop = user_drop; count = 0; *funny_drop_flag = 1; return 0;}
if(count >= 15000) {count = 0; *funny_drop_flag = 1; return 0;} //orient timeout
count++;
return 1;
}
//The Approach function takes as input the state of the robot, variables used to maneuver the robot, and a flag that is set to represent illegal balls
//The other input to this function is a variable that is used to determine when balls are illegal
//The inclusion of the robot state variable was so that the function can be used for both colors of balls that are to be collected (transitions to the next state are correct for each color)
static inline void Approach(float LADARfront, int* funny_ball_flag, float* turn, float* vref,int* RobotState) {
static int count24 = 0;
if(LADARfront < 1) *funny_ball_flag = 1; //this line assumes the count will have incremented slightly before picking up the ball
*turn = 0; //EC JY LM CB move straight
*vref = 0.5; //EC JY LM CB forward velocity
count24++; //EC JY LM CB delay for approach
if (!(*funny_ball_flag)) {
if(!(count24%2000)) //EC JY LM CB after delay
{
*RobotState = (*RobotState == 34) ? 36 : 26; //EC JY LM CB proceed to pick up ball
count24 = 0; //EC JY LM CB reset counter
}
}
else { //EC JY LM CB Undo the current approach and move on
setEPWM5B_RCServo(65);
*vref = -0.5;
count24 -= 2;
if(count24<=0) {
*RobotState = (*RobotState == 34) ? 36 : 26;
count24 = 0;
*funny_ball_flag = 0;
}
}
}
void main(void)
{
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
InitSysCtrl();
InitGpio();
InitSE423DefaultGPIO();
//Scope for Timing
GPIO_SetupPinMux(11, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(11, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPACLEAR.bit.GPIO11 = 1;
GPIO_SetupPinMux(32, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(32, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBCLEAR.bit.GPIO32 = 1;
GPIO_SetupPinMux(52, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(52, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBCLEAR.bit.GPIO52 = 1;
GPIO_SetupPinMux(60, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(60, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBCLEAR.bit.GPIO60 = 1;
GPIO_SetupPinMux(61, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(61, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1;
GPIO_SetupPinMux(67, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(67, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPCCLEAR.bit.GPIO67 = 1;
// ----- code for CAN start here -----
//GPIO17 - CANRXB
GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 2);
GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC);
//GPIO12 - CANTXB
GPIO_SetupPinMux(12, GPIO_MUX_CPU1, 2);
GPIO_SetupPinOptions(12, GPIO_OUTPUT, GPIO_PUSHPULL);
// ----- code for CAN end here -----
// ----- code for CAN start here -----
// Initialize the CAN controller
InitCANB();
// Set up the CAN bus bit rate to 1000 kbps
setCANBitRate(200000000, 1000000);
// Enables Interrupt line 0, Error & Status Change interrupts in CAN_CTL register.
CanbRegs.CAN_CTL.bit.IE0= 1;
CanbRegs.CAN_CTL.bit.EIE= 1;
// ----- code for CAN end here -----
// Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this project
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TIMER0_INT = &cpu_timer0_isr;
PieVectTable.TIMER1_INT = &cpu_timer1_isr;
PieVectTable.TIMER2_INT = &cpu_timer2_isr;
PieVectTable.SCIA_RX_INT = &RXAINT_recv_ready;
PieVectTable.SCIB_RX_INT = &RXBINT_recv_ready;
PieVectTable.SCIC_RX_INT = &RXCINT_recv_ready;
PieVectTable.SCID_RX_INT = &RXDINT_recv_ready;
PieVectTable.SCIA_TX_INT = &TXAINT_data_sent;
PieVectTable.SCIB_TX_INT = &TXBINT_data_sent;
PieVectTable.SCIC_TX_INT = &TXCINT_data_sent;
PieVectTable.SCID_TX_INT = &TXDINT_data_sent;
PieVectTable.ADCC1_INT = &ADCC_ISR;
PieVectTable.SPIB_RX_INT = &SPIB_isr;
PieVectTable.EMIF_ERROR_INT = &SWI1_HighestPriority; // Using Interrupt12 interrupts that are not used as SWIs
PieVectTable.RAM_CORRECTABLE_ERROR_INT = &SWI2_MiddlePriority;
PieVectTable.FLASH_CORRECTABLE_ERROR_INT = &SWI3_LowestPriority;
// ----- code for CAN start here -----
PieVectTable.CANB0_INT = &can_isr;
// ----- code for CAN end here -----
EDIS; // This is needed to disable write to EALLOW protected registers
// Initialize the CpuTimers Device Peripheral. This function can be
// found in F2837xD_CpuTimers.c
InitCpuTimers();
// Configure CPU-Timer 0, 1, and 2 to interrupt every second:
// 200MHz CPU Freq, Period (in uSeconds)
ConfigCpuTimer(&CpuTimer0, LAUNCHPAD_CPU_FREQUENCY, 10000); // Currently not used for any purpose
ConfigCpuTimer(&CpuTimer1, LAUNCHPAD_CPU_FREQUENCY, 100000); // !!!!! Important, Used to command LADAR every 100ms. Do not Change.
ConfigCpuTimer(&CpuTimer2, LAUNCHPAD_CPU_FREQUENCY, 40000); // Currently not used for any purpose
// Enable CpuTimer Interrupt bit TIE
CpuTimer0Regs.TCR.all = 0x4000;
CpuTimer1Regs.TCR.all = 0x4000;
CpuTimer2Regs.TCR.all = 0x4000;
DELAY_US(1000000); // Delay 1 second giving Lidar Time to power on after system power on
init_serialSCIB(&SerialB,19200);
init_serialSCIC(&SerialC,19200);
for (LADARi = 0; LADARi < 228; LADARi++) {
ladar_data[LADARi].angle = ((3*LADARi+44)*0.3515625-135)*0.01745329; //0.017453292519943 is pi/180, multiplication is faster; 0.3515625 is 360/1024
}
init_eQEPs();
init_EPWM1and2();
init_RCServoPWM_3AB_5AB_6A();
init_ADCsAndDACs();
setupSpib();
EALLOW;
EPwm4Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group
EPwm4Regs.TBCTL.bit.CTRMODE = 3; // freeze counter
EPwm4Regs.ETSEL.bit.SOCASEL = 2; // Select Event when counter equal to PRD
EPwm4Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm4Regs.TBCTR = 0x0; // Clear counter
EPwm4Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
EPwm4Regs.TBCTL.bit.PHSEN = 0; // Disable phase loading
EPwm4Regs.TBCTL.bit.CLKDIV = 0; // divide by 1 50Mhz Clock
EPwm4Regs.TBPRD = 50000; // Set Period to 1ms sample. Input clock is 50MHz.
// Notice here that we are not setting CMPA or CMPB because we are not using the PWM signal
EPwm4Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA
//EPwm4Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, wait to do this right before enabling interrupts
EDIS;
// Enable CPU int1 which is connected to CPU-Timer 0, CPU int13
// which is connected to CPU-Timer 1, and CPU int 14, which is connected
// to CPU-Timer 2: int 12 is for the SWI.
IER |= M_INT1;
IER |= M_INT6;
IER |= M_INT8; // SCIC SCID
IER |= M_INT9; // SCIA
IER |= M_INT12;
IER |= M_INT13;
IER |= M_INT14;
// Enable TINT0 in the PIE: Group 1 interrupt 7
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
PieCtrlRegs.PIEIER1.bit.INTx3 = 1;
PieCtrlRegs.PIEIER6.bit.INTx3 = 1;
PieCtrlRegs.PIEIER12.bit.INTx9 = 1; //SWI1
PieCtrlRegs.PIEIER12.bit.INTx10 = 1; //SWI2
PieCtrlRegs.PIEIER12.bit.INTx11 = 1; //SWI3 Lowest priority
// ----- code for CAN start here -----
// Enable CANB in the PIE: Group 9 interrupt 7
PieCtrlRegs.PIEIER9.bit.INTx7 = 1;
// ----- code for CAN end here -----
// ----- code for CAN start here -----
// Enable the CAN interrupt signal
CanbRegs.CAN_GLB_INT_EN.bit.GLBINT0_EN = 1;
// ----- code for CAN end here -----
//Outer Arena Square Perimeter (waypoints for Scanning the corners of the arena)
robotdest[0].x = 0; robotdest[0].y = 2; //Enter the Arena
robotdest[1].x = -4; robotdest[1].y = 2;
robotdest[2].x = -4; robotdest[2].y = 10;
robotdest[3].x = 4; robotdest[3].y = 10;
robotdest[4].x = 4; robotdest[4].y = 2;
robotdest[5].x = 0; robotdest[5].y = 2; //Position back at the start
//Arena Searching Waypoints (used to search for balls in the arena)
scandest[0].x = 0; scandest[0].y = 2; //this point is added for smooth transitions between scanning and searching states
//outer square perimeter
scandest[1].x = -4.4; scandest[1].y = 1.5;
scandest[2].x = -4.4; scandest[2].y = 10;
scandest[3].x = 4.4; scandest[3].y = 10;
scandest[4].x = 4.4; scandest[4].y = 1.5;
//inner square perimeter
scandest[5].x = -2.4; scandest[5].y = 3;
scandest[6].x = -2.4; scandest[6].y = 7;
scandest[7].x = 2.4; scandest[7].y = 7;
scandest[8].x = 2.4; scandest[8].y = 3;
//Center line
scandest[9].x = 0; scandest[9].y = 7;
// scandest[9].x = 2.4; scandest[9].y = 3; //to use when avoiding placing a waypoint inside of a centrally located obstacle
scandest[10].x = 0; scandest[10].y = 1;
//the robot will go to deposit the balls at the right tags after this (check goal_dest array)
// ROBOTps will be updated by Optitrack during gyro calibration
// TODO: specify the starting position of the robot
ROBOTps.x = 0; //the estimate in array form (useful for matrix operations)
ROBOTps.y = 0;
ROBOTps.theta = 0; // was -PI: need to flip OT ground plane to fix this
x_pred[0][0] = ROBOTps.x; //estimate in structure form (useful elsewhere)
x_pred[1][0] = ROBOTps.y;
x_pred[2][0] = ROBOTps.theta;
AdccRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear interrupt flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
SpibRegs.SPIFFRX.bit.RXFFOVFCLR=1; // Clear Overflow flag
SpibRegs.SPIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;
EPwm4Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode
init_serialSCIA(&SerialA,115200);
init_serialSCID(&SerialD,2083332);
// Enable global Interrupts and higher priority real-time debug events
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// ----- code for CAN start here -----
// Measured Distance from 1
// Initialize the receive message object 1 used for receiving CAN messages.
// Message Object Parameters:
// Message Object ID Number: 1
// Message Identifier: 0x060b0101
// Message Frame: Standard
// Message Type: Receive
// Message ID Mask: 0x0
// Message Object Flags: Receive Interrupt
// Message Data Length: 8 Bytes (Note that DLC field is a "don't care"
// for a Receive mailbox)
//
CANsetupMessageObject(CANB_BASE, RX_MSG_OBJ_ID_1, 0x060b0101, CAN_MSG_FRAME_EXT,
CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,
RX_MSG_DATA_LENGTH);
// Measured Distance from 2
// Initialize the receive message object 2 used for receiving CAN messages.
// Message Object Parameters:
// Message Object ID Number: 2
// Message Identifier: 0x060b0102
// Message Frame: Standard
// Message Type: Receive
// Message ID Mask: 0x0
// Message Object Flags: Receive Interrupt
// Message Data Length: 8 Bytes (Note that DLC field is a "don't care"
// for a Receive mailbox)
//
CANsetupMessageObject(CANB_BASE, RX_MSG_OBJ_ID_2, 0x060b0102, CAN_MSG_FRAME_EXT,
CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,
RX_MSG_DATA_LENGTH);
// Measurement Quality from 1
// Initialize the receive message object 2 used for receiving CAN messages.
// Message Object Parameters:
// Message Object ID Number: 3
// Message Identifier: 0x060b0201
// Message Frame: Standard
// Message Type: Receive
// Message ID Mask: 0x0
// Message Object Flags: Receive Interrupt
// Message Data Length: 8 Bytes (Note that DLC field is a "don't care"
// for a Receive mailbox)
//
CANsetupMessageObject(CANB_BASE, RX_MSG_OBJ_ID_3, 0x060b0201, CAN_MSG_FRAME_EXT,
CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,
RX_MSG_DATA_LENGTH);
// Measurement Quality from 2
// Initialize the receive message object 2 used for receiving CAN messages.
// Message Object Parameters:
// Message Object ID Number: 4
// Message Identifier: 0x060b0202
// Message Frame: Standard
// Message Type: Receive
// Message ID Mask: 0x0
// Message Object Flags: Receive Interrupt
// Message Data Length: 8 Bytes (Note that DLC field is a "don't care"
// for a Receive mailbox)
//
CANsetupMessageObject(CANB_BASE, RX_MSG_OBJ_ID_4, 0x060b0202, CAN_MSG_FRAME_EXT,
CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,
RX_MSG_DATA_LENGTH);
//
// Start CAN module operations
//
CanbRegs.CAN_CTL.bit.Init = 0;
CanbRegs.CAN_CTL.bit.CCE = 0;
// ----- code for CAN end here -----
char S_command[19] = "S1152000124000\n";//this change the baud rate to 115200
uint16_t S_len = 19;
serial_sendSCIC(&SerialC, S_command, S_len);
DELAY_US(1000000); // Delay letting Lidar change its Baud rate
init_serialSCIC(&SerialC,115200);
// LED1 is GPIO22
GpioDataRegs.GPACLEAR.bit.GPIO22 = 1;
// LED2 is GPIO94
GpioDataRegs.GPCCLEAR.bit.GPIO94 = 1;
// LED3 is GPIO95
GpioDataRegs.GPCCLEAR.bit.GPIO95 = 1;
// LED4 is GPIO97
GpioDataRegs.GPDCLEAR.bit.GPIO97 = 1;
// LED5 is GPIO111
GpioDataRegs.GPDCLEAR.bit.GPIO111 = 1;
// // IDLE loop. Just sit and loop forever (optional):
while(1)
{
if (UARTPrint == 1 ) {
if (readbuttons() == 1) {
UART_printfLine(1,"Vrf:%.2f trn:%.2f",vref,turn);
// UART_printfLine(1,"x:%.2f:y:%.2f:a%.2f",ROBOTps.x,ROBOTps.y,ROBOTps.theta);
UART_printfLine(2,"F%.4f R%.4f",LADARfront,LADARrightfront);
} else if (readbuttons() == 0) {
// UART_printfLine(1,"P:(%.1f,%.1f), G:(%.1f,%.1f)", goal_dest[0].x, goal_dest[0].y, goal_dest[1].x, goal_dest[1].y);
UART_printfLine(1,"tagthz: %.1f", tagthetaz);
UART_printfLine(2,"State: %d", RobotState);
// UART_printfLine(2,"G_X: %.2f, G_Y: %.2f", goal_dest[1].x, goal_dest[1].y);
// UART_printfLine(1,"P1A:%.0fC:%.0fR:%.0f",MaxAreaThreshold1,MaxColThreshold1,MaxRowThreshold1); // EC JY LM CBPURPLE
// UART_printfLine(2,"G1A:%.0fC:%.0fR:%.0f",MaxAreaThreshold2,MaxColThreshold2,MaxRowThreshold2); // EC JY LM CB GREEN
//UART_printfLine(1,"LV1:%.3f LV2:%.3f",printLV1,printLV2);
//UART_printfLine(2,"Ln1:%.3f Ln2:%.3f",printLinux1,printLinux2);
} else if (readbuttons() == 2) {
UART_printfLine(1,"P2A:%.0fC:%.0fR:%.0f",NextLargestAreaThreshold1,NextLargestColThreshold1,NextLargestRowThreshold1);
UART_printfLine(2,"G2A:%.0fC:%.0fR:%.0f",NextLargestAreaThreshold2,NextLargestColThreshold2,NextLargestRowThreshold2);
// UART_printfLine(1,"%.2f %.2f",adcC2Volt,adcC3Volt);
// UART_printfLine(2,"%.2f %.2f",adcC4Volt,adcC5Volt);
} else if (readbuttons() == 4) {
UART_printfLine(1,"P3A:%.0fC:%.0fR:%.0f",NextNextLargestAreaThreshold1,NextNextLargestColThreshold1,NextNextLargestRowThreshold1);
UART_printfLine(2,"G3A:%.0fC:%.0fR:%.0f",NextNextLargestAreaThreshold2,NextNextLargestColThreshold2,NextNextLargestRowThreshold2);
// UART_printfLine(1,"L:%.3f R:%.3f",LeftVel,RightVel);
// UART_printfLine(2,"uL:%.2f uR:%.2f",uLeft,uRight);
} else if (readbuttons() == 8) {
UART_printfLine(1,"020x%.2f y%.2f",ladar_pts[20].x,ladar_pts[20].y);
UART_printfLine(2,"150x%.2f y%.2f",ladar_pts[150].x,ladar_pts[150].y);
} else if (readbuttons() == 3) {
UART_printfLine(1,"Vrf:%.2f trn:%.2f",vref,turn);
UART_printfLine(2,"MPU:%.2f LPR:%.2f",gyro9250_radians,gyroLPR510_radians);
} else if (readbuttons() == 5) {
UART_printfLine(1,"Ox:%.2f:Oy:%.2f:Oa%.2f",OPTITRACKps.x,OPTITRACKps.y,OPTITRACKps.theta);
UART_printfLine(2,"State:%d : %d",RobotState,statePos);
} else if (readbuttons() == 6) {
UART_printfLine(1,"D1 %ld D2 %ld",dis_1,dis_2);
UART_printfLine(2,"St1 %ld St2 %ld",measure_status_1,measure_status_2);
} else if (readbuttons() == 7) {
UART_printfLine(1,"%.0f,%.1f,%.1f,%.1f",tagid,tagx,tagy,tagz);
UART_printfLine(2,"%.1f,%.1f,%.1f",tagthetax,tagthetay,tagthetaz);
}
UARTPrint = 0;
}
}
}
__interrupt void SPIB_isr(void){
uint16_t i;
GpioDataRegs.GPBSET.bit.GPIO32 = 1;
GpioDataRegs.GPCSET.bit.GPIO66 = 1; //Pull CS high as done R/W
GpioDataRegs.GPASET.bit.GPIO29 = 1; // Pull CS high for DAN28027
if (CurrentChip == MPU9250) {
for (i=0; i<8; i++) {
readdata[i] = SpibRegs.SPIRXBUF; // readdata[0] is garbage
}
PostSWI1(); // Manually cause the interrupt for the SWI1
} else if (CurrentChip == DAN28027) {
DAN28027Garbage = SpibRegs.SPIRXBUF;
dan28027adc1 = SpibRegs.SPIRXBUF;
dan28027adc2 = SpibRegs.SPIRXBUF;
CurrentChip = MPU9250;
SpibRegs.SPIFFCT.bit.TXDLY = 0;
}
SpibRegs.SPIFFRX.bit.RXFFOVFCLR=1; // Clear Overflow flag
SpibRegs.SPIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;
GpioDataRegs.GPBCLEAR.bit.GPIO32 = 1;
}
//adcd1 pie interrupt
__interrupt void ADCC_ISR (void)
{
GpioDataRegs.GPASET.bit.GPIO11 = 1;
adcc2result = AdccResultRegs.ADCRESULT0;
adcc3result = AdccResultRegs.ADCRESULT1;
adcc4result = AdccResultRegs.ADCRESULT2;
adcc5result = AdccResultRegs.ADCRESULT3;
// Here covert ADCIND0 to volts
adcC2Volt = adcc2result*3.0/4095.0;
adcC3Volt = adcc3result*3.0/4095.0;
adcC4Volt = adcc4result*3.0/4095.0;
adcC5Volt = adcc5result*3.0/4095.0;
if (MPU9250ignoreCNT >= 1) {
CurrentChip = MPU9250;
SpibRegs.SPIFFCT.bit.TXDLY = 0;
SpibRegs.SPIFFRX.bit.RXFFIL = 8;
GpioDataRegs.GPCCLEAR.bit.GPIO66 = 1;
SpibRegs.SPITXBUF = ((0x8000)|(0x3A00));
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
} else {
MPU9250ignoreCNT++;
}
numADCCcalls++;
AdccRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear interrupt flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
GpioDataRegs.GPACLEAR.bit.GPIO11 = 1;
}
// cpu_timer0_isr - CPU Timer0 ISR
__interrupt void cpu_timer0_isr(void)
{
CpuTimer0.InterruptCount++;
numTimer0calls++;
if ((numTimer0calls%5) == 0) {
// Blink LaunchPad Red LED
//GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;
}
// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
// cpu_timer1_isr - CPU Timer1 ISR
__interrupt void cpu_timer1_isr(void)
{
serial_sendSCIC(&SerialC, G_command, G_len);
CpuTimer1.InterruptCount++;
}
// cpu_timer2_isr CPU Timer2 ISR
__interrupt void cpu_timer2_isr(void)
{
// Blink LaunchPad Blue LED
//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
CpuTimer2.InterruptCount++;
//Code used to test the operation of the robot's door
//RCangle = readEncWheel();
// setEPWM3A_RCServo(RCangle1);
// setEPWM3B_RCServo(RCangle2);
// setEPWM5A_RCServo(RCangle3); // camera 0 to 90
// setEPWM5B_RCServo(RCangle4); // door 0 to 70
// setEPWM6A_RCServo(RCangle5); // sorter -50 to 35
if ((CpuTimer2.InterruptCount % 10) == 0) {
UARTPrint = 1;
}
}
void setF28027EPWM1A(float controleffort){
if (controleffort < -10) {
controleffort = -10;
}
if (controleffort > 10) {
controleffort = 10;
}
float value = (controleffort+10)*3000.0/20.0;
EPwm1A_F28027 = (int16_t)value; // Set global variable that is sent over SPI to F28027
}
void setF28027EPWM2A(float controleffort){
if (controleffort < -10) {
controleffort = -10;
}
if (controleffort > 10) {
controleffort = 10;
}
float value = (controleffort+10)*3000.0/20.0;
EPwm2A_F28027 = (int16_t)value; // Set global variable that is sent over SPI to F28027
}
//
// Connected to PIEIER12_9 (use MINT12 and MG12_9 masks):
//
__interrupt void SWI1_HighestPriority(void) // EMIF_ERROR
{
GpioDataRegs.GPBSET.bit.GPIO61 = 1;
// Set interrupt priority:
volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER12.all;
IER |= M_INT12;
IER &= MINT12; // Set "global" priority
PieCtrlRegs.PIEIER12.all &= MG12_9; // Set "group" priority
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
__asm(" NOP");
EINT;
//##############################################################################################################
IMU_data[0] = readdata[1];
IMU_data[1] = readdata[2];
IMU_data[2] = readdata[3];
IMU_data[3] = readdata[5];
IMU_data[4] = readdata[6];
IMU_data[5] = readdata[7];
accelx = (((float)(IMU_data[0]))*4.0/32767.0);
accely = (((float)(IMU_data[1]))*4.0/32767.0);
accelz = (((float)(IMU_data[2]))*4.0/32767.0);
gyrox = (((float)(IMU_data[3]))*250.0/32767.0);
gyroy = (((float)(IMU_data[4]))*250.0/32767.0);
gyroz = (((float)(IMU_data[5]))*250.0/32767.0);
//EC JY LM CB The below functions were found using MATLAB to deduce the relation between
// EC JY LM CB where the balls are found in the camera output with a physical distance in actuality
// EC JY LM CB FUNCTION FOR PURPLE CENTROID TO DISTANCE
x = MaxRowThreshold1; //EC JY LM CB Represents the middle distance coordinate for a purple ball
//ePRowCentroid = -0.002778 * x * x * x +0.325 *x*x - 12.78*x+226;
ePDist = -3.107882829244972e-04 * x * x * x + 8.208025720409413e-02 *x*x -7.432333889021033e+00*x+ 2.475813765182145e+02;
//eGRowCentroid
x = MaxRowThreshold2; //EC JY LM CB Represents the middle distance coordinate for a green ball
eGDist = -1.946589446589468e-04 * x *x *x + 5.332368082368142e-02 * x *x -5.111990025740080e+00 *x + 1.868004826254842e+02;
if(calibration_state == 0){
calibration_count++;
if (calibration_count == 2000) {
calibration_state = 1;
calibration_count = 0;
}
} else if(calibration_state == 1){
accelx_offset+=accelx;
accely_offset+=accely;
accelz_offset+=accelz;
gyrox_offset+=gyrox;
gyroy_offset+=gyroy;
gyroz_offset+=gyroz;
gyroLPR510_offset+=adcC5Volt;
calibration_count++;
if (calibration_count == 2000) {
calibration_state = 2;
accelx_offset/=2000.0;
accely_offset/=2000.0;
accelz_offset/=2000.0;
gyrox_offset/=2000.0;
gyroy_offset/=2000.0;
gyroz_offset/=2000.0;
gyroLPR510_offset/=2000.0;
calibration_count = 0;
}
} else if(calibration_state == 2) {
gyroLPR510_drift += (((adcC5Volt-gyroLPR510_offset) + old_gyroLPR510)*.0005)/(2000);
old_gyroLPR510 = adcC5Volt-gyroLPR510_offset;
gyro9250_drift += (((gyroz-gyroz_offset) + old_gyro9250)*.0005)/(2000);
old_gyro9250 = gyroz-gyroz_offset;
calibration_count++;
if (calibration_count == 2000) {
calibration_state = 3;
calibration_count = 0;
doneCal = 1;
newOPTITRACKpose = 0;
}
} else if(calibration_state == 3){
accelx -=(accelx_offset);
accely -=(accely_offset);
accelz -=(accelz_offset);
gyrox -= gyrox_offset;
gyroy -= gyroy_offset;
gyroz -= gyroz_offset;
...
This file has been truncated, please download it to see its full contents.
Comments