//#############################################################################
// FILE: labstarter_main.c
//
// TITLE: Lab Starter
//#############################################################################
// 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 "driverlib.h"
#include "device.h"
#include "f28379dSerial.h"
#include "LEDPatterns.h"
#include "song.h"
#include "dsp.h"
#include "fpu32/fpu_rfft.h"
#define PI 3.1415926535897932384626433832795
#define TWOPI 6.283185307179586476925286766559
#define HALFPI 1.5707963267948966192313216916398
#define RADSTOFT 0.10788008 // 1/9.269552
// Interrupt Service Routines predefinition
__interrupt void cpu_timer0_isr(void);
__interrupt void cpu_timer1_isr(void);
__interrupt void cpu_timer2_isr(void);
__interrupt void SPIB_isr(void);
__interrupt void SWI_isr(void);
__interrupt void ADCA_ISR(void) ;
void serialRXA(serial_t *s, char data);
void serialRXC(serial_t *s, char data);
void setupSpib(void);
void init_eQEPs(void);
float readEncLeft(void);
float readEncRight(void);
void setEPWM2A(float ctreff);
void setEPWM2B(float ctreff);
void setDACA(float dacouta);
void setDACB(float dacoutb);
// Count variables
uint32_t numTimer0calls = 0;
uint32_t numTimer1calls = 0;
uint32_t numSPIcalls = 0;
uint32_t numSWIcalls = 0;
uint32_t numRXA = 0;
uint16_t UARTPrint = 0;
uint16_t LEDdisplaynum = 0;
uint32_t adcacount = 0;
int16_t ESP8266whichcommand = 0;
int16_t ESP8266insidecommands = 0;
//flags
int16_t updown = 1;
//encoder readings
float rightrads = 0.0;
float leftrads = 0.0;
float rightrads_1 = 0.0;
float leftrads_1 = 0.0;
//control eff
float uRight = 5.0;
float uLeft = 5.0;
float ubal = 0;
// reference / desired values
float Vref = 0.2;
float turn_ref = 0.5;
float turn_ref_1 = 0;
//gains
float K1 = -60.0;
float K2 = -6.0;
float K3 = -1.1;
float Kp = 3.0;
float Ki = 20.0;
float Kd = 0.08;
//wheel position
float pLeft_k = 0.0; //current position
float pLeft_k_1 = 0.0; //previous position
float pRight_k = 0.0;
float pRight_k_1 = 0.0;
//wheel velocities
float vLeft_k = 0.0;
float vLeft_k_1 = 0;
float vRight_k = 0.0;
float vRight_k_1=0;
//turn position, velocity
float WhlDiff = 0;
float vel_WhlDiff = 0;
float WhlDiff_1 = 0;
float vel_WhlDiff_1 = 0;
float turn = 0;
float turnrate = 0;
float turnrate_1 = 0;
//error terms
float e_Diff_k = 0;
float e_Diff_k_1 = 0;
//Integral terms
float I_Diff_k = 0;
float I_Diff_k_1 = 0;
float I_t_rate_k = 0;
float I_t_rate_k_1 = 0;
//adca readings
int16_t adca0result = 0;
int16_t adca1result = 0;
float adca0volts = 0;
float adca1volts = 0;
//gyro and accel readings
int16_t dummy = 0;
int16_t gyroXraw = 0;
int16_t gyroYraw = 0;
int16_t gyroZraw = 0;
int16_t acclXraw = 0;
int16_t acclYraw = 0;
int16_t acclZraw = 0;
float gyrox = 0.0;
float gyroy = 0.0;
float gyroz = 0.0;
float accelx = 0.0;
float accely = 0.0;
float accelz = 0.0;
//offsets
float accelx_offset = 0;
float accely_offset = 0;
float accelz_offset = 0;
float gyrox_offset = 0;
float gyroy_offset = 0;
float gyroz_offset = 0;
float FB_offset = 0.27;
//calibration stuff
float accelzBalancePoint = -.773;
int16 IMU_data[9];
uint16_t temp=0;
int16_t doneCal = 0;
float tilt_value = 0;
float tilt_array[4] = {0, 0, 0, 0};
float gyro_value = 0;
float gyro_array[4] = {0, 0, 0, 0};
float LeftWheelArray[4] = {0,0,0,0};
float RightWheelArray[4] = {0,0,0,0};
float LeftWheel = 0;
float RightWheel = 0;
// Kalman Filter vars
float T = 0.001; //sample rate, 1ms
float Q = 0.01; // made global to enable changing in runtime
float R = 25000;//50000;
float kalman_tilt = 0;
float kalman_P = 22.365;
int16_t SpibNumCalls = -1;
float pred_P = 0;
float kalman_K = 0;
int32_t timecount = 0;
int16_t calibration_state = 0;
int32_t calibration_count = 0;
void main(void)
{
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
InitSysCtrl();
InitGpio();
// Blue LED on LuanchPad
GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPASET.bit.GPIO31 = 1;
// Red LED on LaunchPad
GPIO_SetupPinMux(34, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(34, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBSET.bit.GPIO34 = 1;
// LED1 and PWM Pin
GPIO_SetupPinMux(22, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(22, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPACLEAR.bit.GPIO22 = 1;
// LED2
GPIO_SetupPinMux(94, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(94, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPCCLEAR.bit.GPIO94 = 1;
// LED3
GPIO_SetupPinMux(95, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(95, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPCCLEAR.bit.GPIO95 = 1;
// LED4
GPIO_SetupPinMux(97, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(97, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPDCLEAR.bit.GPIO97 = 1;
// LED5
GPIO_SetupPinMux(111, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(111, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPDCLEAR.bit.GPIO111 = 1;
// LED6
GPIO_SetupPinMux(130, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(130, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPECLEAR.bit.GPIO130 = 1;
// LED7
GPIO_SetupPinMux(131, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(131, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPECLEAR.bit.GPIO131 = 1;
// LED8
GPIO_SetupPinMux(25, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(25, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPACLEAR.bit.GPIO25 = 1;
// LED9
GPIO_SetupPinMux(26, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(26, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPACLEAR.bit.GPIO26 = 1;
// LED10
GPIO_SetupPinMux(27, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(27, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPACLEAR.bit.GPIO27 = 1;
// LED11
GPIO_SetupPinMux(60, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(60, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBCLEAR.bit.GPIO60 = 1;
// LED12
GPIO_SetupPinMux(61, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(61, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBCLEAR.bit.GPIO61 = 1;
// LED13
GPIO_SetupPinMux(157, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(157, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPECLEAR.bit.GPIO157 = 1;
// LED14
GPIO_SetupPinMux(158, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(158, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPECLEAR.bit.GPIO158 = 1;
// LED15
GPIO_SetupPinMux(159, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(159, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPECLEAR.bit.GPIO159 = 1;
// LED16
GPIO_SetupPinMux(160, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(160, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPFCLEAR.bit.GPIO160 = 1;
//WIZNET Reset
GPIO_SetupPinMux(0, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(0, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPASET.bit.GPIO0 = 1;
//ESP8266 Reset
GPIO_SetupPinMux(1, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(1, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPASET.bit.GPIO1 = 1;
//SPIRAM CS Chip Select
GPIO_SetupPinMux(19, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(19, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPASET.bit.GPIO19 = 1;
//DRV8874 #1 DIR Direction
GPIO_SetupPinMux(29, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(29, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPASET.bit.GPIO29 = 1;
//DRV8874 #2 DIR Direction
GPIO_SetupPinMux(32, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(32, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPBSET.bit.GPIO32 = 1;
//DAN28027 CS Chip Select
GPIO_SetupPinMux(9, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(9, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPASET.bit.GPIO9 = 1;
//MPU9250 CS Chip Select
GPIO_SetupPinMux(66, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(66, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPCSET.bit.GPIO66 = 1;
//WIZNET CS Chip Select
GPIO_SetupPinMux(125, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(125, GPIO_OUTPUT, GPIO_PUSHPULL);
GpioDataRegs.GPDSET.bit.GPIO125 = 1;
//PushButton 1
GPIO_SetupPinMux(4, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(4, GPIO_INPUT, GPIO_PULLUP);
//PushButton 2
GPIO_SetupPinMux(5, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(5, GPIO_INPUT, GPIO_PULLUP);
//PushButton 3
GPIO_SetupPinMux(6, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(6, GPIO_INPUT, GPIO_PULLUP);
//PushButton 4
GPIO_SetupPinMux(7, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(7, GPIO_INPUT, GPIO_PULLUP);
//Joy Stick Pushbutton
GPIO_SetupPinMux(8, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(8, GPIO_INPUT, GPIO_PULLUP);
//EPWM2A
GPIO_SetupPinMux(2, GPIO_MUX_CPU1, 1);
//EPWM2B
GPIO_SetupPinMux(3, GPIO_MUX_CPU1, 1);
// Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
EALLOW;
//similar settings to epwm12
EPwm2Regs.TBCTL.bit.FREE_SOFT = 0x2;
EPwm2Regs.TBCTL.bit.PHSEN = 0;
EPwm2Regs.TBCTL.bit.CTRMODE=0;
EPwm2Regs.TBCTL.bit.CLKDIV = 0;
EPwm2Regs.TBCTR = 0x0;
//same 50us period
EPwm2Regs.TBPRD = 2500;
//start at full duty cycle
EPwm2Regs.CMPA.bit.CMPA = 2500;
EPwm2Regs.TBPHS.bit.TBPHS =0;
EPwm2Regs.AQCTLA.bit.CAU = 0x1;
EPwm2Regs.AQCTLA.bit.ZRO = 0x2;
EDIS;
EALLOW;
//set up the other motor, only need to specify registers specific to B
EPwm2Regs.CMPB.bit.CMPB = 2500;
EPwm2Regs.AQCTLB.bit.CBU = 0x1;
EPwm2Regs.AQCTLB.bit.ZRO = 0x2;
EDIS;
EALLOW;
EPwm5Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group
EPwm5Regs.TBCTL.bit.CTRMODE = 3; // freeze counter
EPwm5Regs.ETSEL.bit.SOCASEL = 0x2; // Select Event when counter equal to PRD
EPwm5Regs.ETPS.bit.SOCAPRD = 0x1; // Generate pulse on 1st event (“pulse” is the same as “trigger”)
EPwm5Regs.TBCTR = 0x0; // Clear counter
EPwm5Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
EPwm5Regs.TBCTL.bit.PHSEN = 0; // Disable phase loading
EPwm5Regs.TBCTL.bit.CLKDIV = 0; // divide by 1 50Mhz Clock
EPwm5Regs.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
EPwm5Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA
EPwm5Regs.TBCTL.bit.CTRMODE = 0x0; //unfreeze, and enter up count mode
EDIS;
EALLOW;
//write configurations for all ADCs ADCA, ADCB, ADCC, ADCD
AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
AdccRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
AdcdRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //read calibration settings
AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //read calibration settings
AdcSetMode(ADC_ADCC, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //read calibration settings
AdcSetMode(ADC_ADCD, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //read calibration settings
//Set pulse positions to late
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcdRegs.ADCCTL1.bit.INTPULSEPOS = 1;
//power up the ADCs
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;
AdcdRegs.ADCCTL1.bit.ADCPWDNZ = 1;
//delay for 1ms to allow ADC time to power up
DELAY_US(1000);
//ADCA
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0x2; //SOC0 will convert Channel you choose Does not have to be A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 99; //sample window is acqps + 1 SYSCLK cycles = 500ns
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0xD;// EPWM5 ADCSOCA or another trigger you choose will trigger SOC0
AdcaRegs.ADCSOC1CTL.bit.CHSEL = 0x3; //SOC1 will convert Channel you choose Does not have to be A1
AdcaRegs.ADCSOC1CTL.bit.ACQPS = 99; //sample window is acqps + 1 SYSCLK cycles = 500ns
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0xD;// EPWM5 ADCSOCA or another trigger you choose will trigger SOC1
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0x1; //set to last SOC that is converted and it will set INT1 flag ADCA1
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
EDIS;
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // For EPWM2A
GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1; // For EPWM2B
EDIS;
// 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.SCIC_RX_INT = &RXCINT_recv_ready;
PieVectTable.SCID_RX_INT = &RXDINT_recv_ready;
PieVectTable.SCIA_TX_INT = &TXAINT_data_sent;
PieVectTable.SCIC_TX_INT = &TXCINT_data_sent;
PieVectTable.SCID_TX_INT = &TXDINT_data_sent;
PieVectTable.SPIB_RX_INT = &SPIB_isr;
PieVectTable.ADCA1_INT = &ADCA_ISR;
PieVectTable.EMIF_ERROR_INT = &SWI_isr;
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, 1 second Period (in uSeconds)
ConfigCpuTimer(&CpuTimer0, 200, 1000);
ConfigCpuTimer(&CpuTimer1, 200, 4000);
ConfigCpuTimer(&CpuTimer2, 200, 40000);
// Enable CpuTimer Interrupt bit TIE
CpuTimer0Regs.TCR.all = 0x4000;
CpuTimer1Regs.TCR.all = 0x4000;
CpuTimer2Regs.TCR.all = 0x4000;
init_serial(&SerialA,115200,serialRXA);
init_serial(&SerialC,115200,serialRXC);
// init_serial(&SerialD,115200,serialRXD);
setupSpib();
init_eQEPs();
// 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.INTx1 = 1;
// Enable SWI in the PIE: Group 12 interrupt 9
PieCtrlRegs.PIEIER12.bit.INTx9 = 1;
PieCtrlRegs.PIEIER6.bit.INTx3 = 1;
// Enable global Interrupts and higher priority real-time debug events
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
serial_send(&SerialC,"AT\r\n",strlen("AT\r\n"));
ESP8266whichcommand = 1;
ESP8266insidecommands = 1;
// IDLE loop. Just sit and loop forever (optional):
while(1)
{
if (UARTPrint == 1 ) {
// serial_printf(&SerialA,"tilt val:%f gyro val:%f left:%f rads/s right:%f rads/s \r\n",tilt_value, gyro_value, LeftWheel, RightWheel);
UARTPrint = 0;
}
}
}
// SWI_isr, Using this interrupt as a Software started interrupt
__interrupt void SWI_isr(void) {
// These three lines of code allow SWI_isr, to be interrupted by other interrupt functions
// making it lower priority than all other Hardware interrupts.
PieCtrlRegs.PIEACK.all = PIEACK_GROUP12;
asm(" NOP"); // Wait one cycle
EINT; // Clear INTM to enable interrupts
////////////
pRight_k = RightWheel; //rads
pLeft_k = LeftWheel; //rads
WhlDiff = pLeft_k - pRight_k;
turn_ref = turn_ref_1 + (0.004 * (turnrate + turnrate_1)*0.5);
e_Diff_k = turn_ref - WhlDiff;
I_Diff_k = I_Diff_k_1 + (0.004 * (e_Diff_k + e_Diff_k_1) * 0.5);
vRight_k = (0.6*vRight_k_1) + 100*(pRight_k-pRight_k_1); // rads/s
vLeft_k = (0.6*vLeft_k_1) + 100*(pLeft_k-pLeft_k_1); // rads/s
vel_WhlDiff = (0.333*vel_WhlDiff_1)+ (166.667*(WhlDiff - WhlDiff_1));
turn = (Kp*e_Diff_k) + (Ki*I_Diff_k) - (Kd*vel_WhlDiff);
if (fabs(turn > 3)) {
I_Diff_k = I_Diff_k_1;
}
if (fabs(turn > 4)) {
turn = 4.0;
}
ubal = -(K1*tilt_value)-(K2*gyro_value)-(K3*(vLeft_k+vRight_k)/2.0);
uRight = (ubal/2.0) - turn + FB_offset;
uLeft = (ubal/2.0) + turn + FB_offset;
setEPWM2A(uRight);
setEPWM2B(-uLeft);
pRight_k_1 = pRight_k;
pLeft_k_1 = pLeft_k;
vRight_k_1 = vRight_k;
vLeft_k_1 = vLeft_k;
WhlDiff_1 = WhlDiff;
vel_WhlDiff_1 = vel_WhlDiff;
e_Diff_k_1 = e_Diff_k;
I_Diff_k_1 = I_Diff_k;
turnrate_1 = turnrate;
turn_ref_1 = turn_ref;
////////////
numSWIcalls++;
DINT;
}
// cpu_timer0_isr - CPU Timer0 ISR
__interrupt void cpu_timer0_isr(void)
{
// CpuTimer0.InterruptCount++;
numTimer0calls++;
// 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)
{
numTimer1calls++;
}
// cpu_timer2_isr CPU Timer2 ISR
__interrupt void cpu_timer2_isr(void)
{
CpuTimer2.InterruptCount++;
}
__interrupt void ADCA_ISR(void){
adcacount++;
//obtain bit vals
adca0result = AdcaResultRegs.ADCRESULT0;
adca1result = AdcaResultRegs.ADCRESULT1;
//covert ADCIND0, ADCIND1 to volts
adca0volts = adca0result*(3.0/4095.0);
adca1volts = adca1result*(3.0/4095.0);
//begin spi transmission
//Clear GPIO9 Low to act as a Slave Select. Right now, just to scope. Later to select DAN28027 chip
GpioDataRegs.GPCCLEAR.bit.GPIO66 = 1;
SpibRegs.SPIFFRX.bit.RXFFIL = 8; // Issue the SPIB_RX_INT when two values are in the RX FIFO
SpibRegs.SPITXBUF = ( 0x8000 | 0x3A00 ); // accl
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0; // something so you can see the pattern on the Oscilloscope
SpibRegs.SPITXBUF = 0;
SpibRegs.SPITXBUF = 0;
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear interrupt flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
__interrupt void SPIB_isr(void){
GpioDataRegs.GPCSET.bit.GPIO66 = 1;
dummy = SpibRegs.SPIRXBUF;
acclXraw = SpibRegs.SPIRXBUF;
acclYraw = SpibRegs.SPIRXBUF;
acclZraw = SpibRegs.SPIRXBUF;
dummy = SpibRegs.SPIRXBUF; // Read first 16 bit value off RX FIFO. Probably is zero since no chip
gyroXraw = SpibRegs.SPIRXBUF; // Read second 16 bit value off RX FIFO. Again probably zero
gyroYraw = SpibRegs.SPIRXBUF;
gyroZraw = SpibRegs.SPIRXBUF;
// GpioDataRegs.GPASET.bit.GPIO9 = 1; // Set GPIO 9 high to end Slave Select. Now to Scope. Later to deselect DAN28027
// Later when actually communicating with the DAN28027 do something with the data. Now do nothing.
accelx = acclXraw*(4.0/32767.0);
accely = acclYraw*(4.0/32767.0);
accelz = acclZraw*(4.0/32767.0);
gyrox = gyroXraw*(250.0/32767.0);
gyroy = gyroYraw*(250.0/32767.0);
gyroz = gyroZraw*(250.0/32767.0);
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;
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;
calibration_count = 0;
doneCal = 1;
}
}
else if(calibration_state == 2){
accelx -=(accelx_offset);
accely -=(accely_offset);
accelz -=(accelz_offset-accelzBalancePoint);
gyrox -= gyrox_offset;
gyroy -= gyroy_offset;
gyroz -= gyroz_offset;
/*--------------Kalman Filtering code start---------------------------------------------------------------------*/
float tiltrate = (gyrox*PI)/180.0; // rad/s
float pred_tilt, z, y, S;
// Prediction Step
pred_tilt = kalman_tilt + T*tiltrate;
pred_P = kalman_P + Q;
// Update Step
z = -accelz; // Note the negative here due to the polarity of AccelZ
y = z - pred_tilt;
S = pred_P + R;
kalman_K = pred_P/S;
kalman_tilt = pred_tilt + kalman_K*y;
kalman_P = (1 - kalman_K)*pred_P;
SpibNumCalls++;
// Kalman Filter used
tilt_array[SpibNumCalls] = kalman_tilt;
gyro_array[SpibNumCalls] = tiltrate;
LeftWheelArray[SpibNumCalls] = -readEncLeft();
RightWheelArray[SpibNumCalls] = readEncRight();
if (SpibNumCalls >= 3) { // should never be greater than 3
tilt_value = (tilt_array[0] + tilt_array[1] + tilt_array[2] + tilt_array[3])/4.0;
gyro_value = (gyro_array[0] + gyro_array[1] + gyro_array[2] + gyro_array[3])/4.0;
LeftWheel=(LeftWheelArray[0]+LeftWheelArray[1]+LeftWheelArray[2]+LeftWheelArray[3])/4.0;
RightWheel=(RightWheelArray[0]+RightWheelArray[1]+RightWheelArray[2]+RightWheelArray[3])/4.0;
SpibNumCalls = -1;
PieCtrlRegs.PIEIFR12.bit.INTx9 = 1; // Manually cause the interrupt for the SWI
}
}
timecount++;
if((timecount%200) == 0) {
if(doneCal == 0) {
GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1; // Blink Blue LED while calibrating
}
GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // Always Block Red LED
UARTPrint = 1; // Tell While loop to print
}
SpibRegs.SPIFFRX.bit.RXFFOVFCLR = 1; // Clear Overflow flag just in case of an overflow
SpibRegs.SPIFFRX.bit.RXFFINTCLR = 1; // Clear RX FIFO Interrupt flag so next interrupt will happen
PieCtrlRegs.PIEACK.all = PIEACK_GROUP6; // Acknowledge INT6 PIE interrupt
}
// This function is called each time a char is recieved over UARTA.
char sendto8266[10];
int16_t sendingto8266 = 0;
int16_t collect = 0;
void serialRXA(serial_t *s, char data) {
numRXA ++;
if (sendingto8266 == 0) {
sendto8266[0] = data;
sendingto8266 = 1;
serial_send(&SerialC,"AT+CIPSEND=0,1\r\n",strlen("AT+CIPSEND=0,1\r\n"));
//serial_send(&SerialC,sendto8266,1);
}
}
char sendback[10];
char past4[4] = {'\0','\0','\0','\0'};
char gusarray[50] ;
float myfloat = 0;
uint16_t turnflag = 0;
uint16_t velflag = 0;
uint16_t fbflag = 0;
uint16_t g= 0;
// This function is called each time a char is received over UARTA.
void serialRXC(serial_t *s, char data) {
if (ESP8266insidecommands == 1) {
if (ESP8266whichcommand == 1) {
past4[0] = data;
if ((past4[0]=='\n') && (past4[1]=='\r') && (past4[2]=='K') && (past4[3]=='O')) {
ESP8266whichcommand = 2;
serial_send(&SerialC,"AT+CWMODE=3\r\n",strlen("AT+CWMODE=3\r\n"));
past4[0] = '\0';
past4[1] = '\0';
past4[2] = '\0';
past4[3] = '\0';
}
past4[3] = past4[2];
past4[2] = past4[1];
past4[1] = past4[0];
} else if (ESP8266whichcommand == 2) {
past4[0] = data;
if ((past4[0]=='\n') && (past4[1]=='\r') && (past4[2]=='K') && (past4[3]=='O')) {
ESP8266whichcommand = 3;
serial_send(&SerialC,"AT+CWJAP=\"MECHNIGHT\",\"f33dback5\"\r\n",strlen("AT+CWJAP=\"MECHNIGHT\",\"f33dback5\"\r\n"));
//serial_send(&SerialC,"AT+CWJAP=\"Jesusloves\",\"n8watchit\"\r\n",strlen("AT+CWJAP=\"JESUSLOVES\",\"n8watchit\"\r\n"));
past4[0] = '\0';
past4[1] = '\0';
past4[2] = '\0';
past4[3] = '\0';
}
past4[3] = past4[2];
past4[2] = past4[1];
past4[1] = past4[0];
} else if (ESP8266whichcommand == 3) {
past4[0] = data;
if ((past4[0]=='\n') && (past4[1]=='\r') && (past4[2]=='K') && (past4[3]=='O')) {
ESP8266whichcommand = 4;
serial_send(&SerialC, "AT+CIPSTA=\"192.168.1.52\"\r\n", strlen("AT+CIPSTA=\"192.168.1.52\"\r\n"));
past4[0] = '\0';
past4[1] = '\0';
past4[2] = '\0';
past4[3] = '\0';
}
past4[3] = past4[2];
past4[2] = past4[1];
past4[1] = past4[0];
} else if (ESP8266whichcommand == 4) {
past4[0] = data;
if ((past4[0]=='\n') && (past4[1]=='\r') && (past4[2]=='K') && (past4[3]=='O')) {
ESP8266whichcommand = 5;
serial_send(&SerialC,"AT+CIPMUX=1\r\n", strlen("AT+CIPMUX=1\r\n"));
past4[0] = '\0';
past4[1] = '\0';
past4[2] = '\0';
past4[3] = '\0';
}
past4[3] = past4[2];
past4[2] = past4[1];
past4[1] = past4[0];
} else if (ESP8266whichcommand == 5) {
past4[0] = data;
if ((past4[0]=='\n') && (past4[1]=='\r') && (past4[2]=='K') && (past4[3]=='O')) {
ESP8266whichcommand = 6;
serial_send(&SerialC,"AT+CIPSERVER=1,1336\r\n", strlen("AT+CIPSERVER=1,1336\r\n"));
past4[0] = '\0';
past4[1] = '\0';
past4[2] = '\0';
past4[3] = '\0';
}
past4[3] = past4[2];
past4[2] = past4[1];
past4[1] = past4[0];
} else if (ESP8266whichcommand == 6) {
past4[0] = data;
if ((past4[0]=='\n') && (past4[1]=='\r') && (past4[2]=='K') && (past4[3]=='O')) {
ESP8266whichcommand = 12; // should never get in 12
ESP8266insidecommands = 0;
past4[0] = '\0';
past4[1] = '\0';
past4[2] = '\0';
past4[3] = '\0';
}
past4[3] = past4[2];
past4[2] = past4[1];
past4[1] = past4[0];
} else if (ESP8266whichcommand == 12) {
sendback[0] = ' ';
sendback[1] = 'D';
sendback[2] = 'a';
sendback[3] = 'n';
serial_send(&SerialA,sendback,4);
}
sendback[0] = data;
serial_send(&SerialA,sendback,1);
} else { // ESP8266insidecommands == 0
// for now just echo char
if (sendingto8266 == 1) {
if (data == '>') {
serial_send(&SerialC,sendto8266,1);
sendingto8266 = 0;
}
}
sendback[0] = data;
serial_send(&SerialA,sendback,1);
if (collect==0){
if (data == 't'){
collect = 1;
turnflag = 1;
}
else if (data == 'v'){
collect = 1;
velflag = 1;
}
else if (data == 'b'){
collect = 1;
fbflag = 1;
}
}
else{
if (data =='\n'){
gusarray[g]='\0';
sscanf(gusarray,"%f",&myfloat);
if (turnflag == 1){
turnrate = myfloat;
turnflag = 0;
}
else if (velflag == 1){
Vref = myfloat;
velflag = 0;
}
else if (fbflag == 1){
FB_offset = myfloat;
fbflag = 0;
}
collect = 0;
g=0;
}
else{
gusarray[g]=data;
g++;
if (g>=50){
g = 0;
}
}
}
// if (gusarray[0] == 't'){
// turnrate = myfloat;
// }
// else if (gusarray[0] == 'v'){
// Vref = myfloat;
// }
}
}
void setupSpib(void) //Call this function in main() somewhere after the DINT; line of code.
{
int16_t temp = 0;
//Step 1.
GPIO_SetupPinMux(9, GPIO_MUX_CPU1, 0); // Set as GPIO9 and used as DAN28027 SS
GPIO_SetupPinOptions(9, GPIO_OUTPUT, GPIO_PUSHPULL); // Make GPIO9 an Output Pin
GpioDataRegs.GPASET.bit.GPIO9 = 1; //Initially Set GPIO9/SS High so DAN28027 is not selected
GPIO_SetupPinMux(66, GPIO_MUX_CPU1, 0); // Set as GPIO66 and used as MPU-9250 SS
GPIO_SetupPinOptions(66, GPIO_OUTPUT, GPIO_PUSHPULL); // Make GPIO66 an Output Pin
GpioDataRegs.GPCSET.bit.GPIO66 = 1; //Initially Set GPIO66/SS High so MPU-9250 is not selected
GPIO_SetupPinMux(63, GPIO_MUX_CPU1, 15); //Set GPIO63 pin to SPISIMOB
GPIO_SetupPinMux(64, GPIO_MUX_CPU1, 15); //Set GPIO64 pin to SPISOMIB
GPIO_SetupPinMux(65, GPIO_MUX_CPU1, 15); //Set GPIO65 pin to SPICLKB
EALLOW;
GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0; // Enable Pull-ups on SPI PINs Recommended by TI for SPI Pins
GpioCtrlRegs.GPCPUD.bit.GPIO64 = 0;
GpioCtrlRegs.GPCPUD.bit.GPIO65 = 0;
GpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 3; // Set I/O pin to asynchronous mode recommended for SPI
GpioCtrlRegs.GPCQSEL1.bit.GPIO64 = 3; // Set I/O pin to asynchronous mode recommended for SPI
GpioCtrlRegs.GPCQSEL1.bit.GPIO65 = 3; // Set I/O pin to asynchronous mode recommended for SPI
EDIS;
// ---------------------------------------------------------------------------
SpibRegs.SPICCR.bit.SPISWRESET = 0; // Put SPI in Reset
SpibRegs.SPICTL.bit.CLK_PHASE = 1; //This happens to be the mode for both the DAN28027 and
SpibRegs.SPICCR.bit.CLKPOLARITY = 0; //The MPU-9250, Mode 01.
SpibRegs.SPICTL.bit.MASTER_SLAVE = 1; // Set to SPI Master
SpibRegs.SPICCR.bit.SPICHAR = 0xF; // Set to transmit and receive 16 bits each write to SPITXBUF
SpibRegs.SPICTL.bit.TALK = 1; // Enable transmission
SpibRegs.SPIPRI.bit.FREE = 1; // Free run, continue SPI operation
SpibRegs.SPICTL.bit.SPIINTENA = 0; // Disables the SPI interrupt
SpibRegs.SPIBRR.bit.SPI_BIT_RATE = 49; // Set SCLK bit rate to 1 MHz so 1us period. SPI base clock is
// 50MHZ. And this setting divides that base clock to create SCLK’s period
SpibRegs.SPISTS.all = 0x0000; // Clear status flags just in case they are set for some reason
SpibRegs.SPIFFTX.bit.SPIRST = 1;// Pull SPI FIFO out of reset, SPI FIFO can resume transmit or receive.
SpibRegs.SPIFFTX.bit.SPIFFENA = 1; // Enable SPI FIFO enhancements
SpibRegs.SPIFFTX.bit.TXFIFO = 0; // Write 0 to reset the FIFO pointer to zero, and hold in reset
SpibRegs.SPIFFTX.bit.TXFFINTCLR = 1; // Write 1 to clear SPIFFTX[TXFFINT] flag just in case it is set
SpibRegs.SPIFFRX.bit.RXFIFORESET = 0; // Write 0 to reset the FIFO pointer to zero, and hold in reset
SpibRegs.SPIFFRX.bit.RXFFOVFCLR = 1; // Write 1 to clear SPIFFRX[RXFFOVF] just in case it is set
SpibRegs.SPIFFRX.bit.RXFFINTCLR = 1; // Write 1 to clear SPIFFRX[RXFFINT] flag just in case it is set
SpibRegs.SPIFFRX.bit.RXFFIENA = 1; // Enable the RX FIFO Interrupt. RXFFST >= RXFFIL
SpibRegs.SPIFFCT.bit.TXDLY = 0; //Set delay between transmits to 16 spi clocks. Needed by DAN28027 chip
SpibRegs.SPICCR.bit.SPISWRESET = 1; // Pull the SPI out of reset
SpibRegs.SPIFFTX.bit.TXFIFO = 1; // Release transmit FIFO from reset.
SpibRegs.SPIFFRX.bit.RXFIFORESET = 1; // Re-enable receive FIFO operation
SpibRegs.SPICTL.bit.SPIINTENA = 1; // Enables SPI interrupt. !! I don’t think this is needed. Need to Test
SpibRegs.SPIFFRX.bit.RXFFIL =0x10; //Interrupt Level to 16 words or more received into FIFO causes interrupt. This is just the initial setting for the register. Will be changed below
//-----------------------------------------------------------------------------------------------------------------
//Step 2.
// perform a multiple 16 bit transfer to initialize MPU-9250 registers 0x13,0x14,0x15,0x16
// 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C 0x1D, 0x1E, 0x1F. Use only one SS low to high for all these writes
GpioDataRegs.GPCCLEAR.bit.GPIO66 = 1; // Slave Select Low
// To address 00x13 write 0x00
SpibRegs.SPITXBUF = ( 0x1300 | 0x0000 );
// To address 00x14 write 0x00
// To address 00x15 write 0x00
SpibRegs.SPITXBUF = ( 0x0000 | 0x0000 );
// To address 00x16 write 0x00
// To address 00x17 write 0x00
SpibRegs.SPITXBUF = ( 0x0000 | 0x0000 );
// To address 00x18 write 0x00
// To address 00x19 write 0x13
SpibRegs.SPITXBUF = ( 0x0000 | 0x0013 );
// To address 00x1A write 0x02
// To address 00x1B write 0x00
SpibRegs.SPITXBUF = ( 0x0200 | 0x0000 );
// To address 00x1C write 0x08
// To address 00x1D write 0x06
SpibRegs.SPITXBUF = ( 0x0800 | 0x0006 );
// To address 00x1E write 0x00
// To address 00x1F write 0x00
SpibRegs.SPITXBUF = ( 0x0000 | 0x0000 );
// wait for the correct number of 16 bit values to be received into the RX FIFO
while(SpibRegs.SPIFFRX.bit.RXFFST !=7);
...
This file has been truncated, please download it to see its full contents.
Comments
Please log in or sign up to comment.