Nicholas Gustafson
Published

WIFI Controlled Segbot

Segbot that balances with PID control and can be commanded to move through commands in Linux terminal.

IntermediateFull instructions provided358
WIFI Controlled Segbot

Things used in this project

Story

Read more

Schematics

Video

Code

Main C File for Segbot

C/C++
Using the gyro and accelerometer, PID control is implemented to balance the bot. Commands for the rate at which the bot rotate and for the forward/back offset can be made to control whether or not the bot moves or reorients itself. This code also issue AT commands to the ESP 8266 to set up connection with the TCP server as well as telling the bot how to handle serial information received by the ESP8266.
//#############################################################################
// 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.

TCP Client Code

C/C++
This code, when executed in a Linux terminal first makes a connection with the ESP 8266. Once that connection is made, it prompts the use with a menu of options to control the segbot.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <math.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/mman.h>
#include "Practical.h"

int mygetch(void);

#define TCPSENDSIZE 1024
char TCPSendBuff[TCPSENDSIZE];
char commandline[TCPSENDSIZE/2];
int16_t TCPSendBuffLen = 0;
int16_t numBytes = 0;
float turn = 0;
float fboffset=0.3;

int main(int argc, char *argv[]) {

  char mychar;
  int inputdone = 0;
  
//  if (argc < 3 || argc > 4) // Test for correct number of arguments
//    DieWithUserMessage("Parameter(s)",
//        "<Server Address/Name> <Echo Word> [<Server Port/Service>]");

//  char *server = argv[1];     // First arg: server address/name
//  char *echoString = argv[2]; // Second arg: string to echo
  // Third arg (optional): server port/service
//  char *service = (argc == 4) ? argv[3] : "echo";

  char server[] = "192.168.1.52";
  char service[] = "1336";
   
  // Create a connected TCP socket
  int sock = SetupTCPClientSocket(server, service);
  if (sock < 0)
    DieWithUserMessage("SetupTCPClientSocket() failed", "unable to connect");

//  size_t echoStringLen = strlen(echoString); // Determine input length
// stay in this while loop receiving input from the user until user exits by selecting option e or v  
  while (!inputdone) {
		printf("\n\n");
		printf("Menu of Selections\n");
		printf("DO NOT PRESS CTRL-C when in this menu selection\n");
		printf("WASD - increment Forward/Left/Back/Right\n");
		printf("f - enter Desired Velocity Setpoint\n");
		//printf("a - increment Left\n");
		//printf("d - increment Right\n");
		//printf("w - increment Forward\n");
		//printf("s - increment Backward\n");
		printf("r - reset forward/back motion\n");
		printf("q - reset turn\n");
		printf("e - Exit Application\n");
		mychar = (char) mygetch();
		
		switch (mychar) {
		case 'a': //left turn
			if (turn > 0.0) {
				turn = 0.0;
			} else {
				turn = turn - 0.2;
			}
			printf("turn =%.3f\n",turn);
			
			// send new turn value to ESP8266
			TCPSendBuffLen = sprintf(TCPSendBuff,"t%.5f\n",turn); //t for turn
			  // Send the string to the server
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			
			break;
		case 'd':  //right turn                              
			if (turn < 0.0) {
				turn = 0.0;
			} else {
				turn = turn + 0.2;
			}
			printf("turn =%.3f\n",turn);
			
			// send new turn value to ESP8266
			TCPSendBuffLen = sprintf(TCPSendBuff,"t%.5f\n",turn);
			  // Send the string to the server
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			break;
			
			
		case 'q': //reset turn                                
			turn = 0.0;
			printf("turn =%.3f\n",turn);
			
			// send new turn value to ESP8266
			TCPSendBuffLen = sprintf(TCPSendBuff,"t%.5f\n",turn);
			  // Send the string to the server
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			break;
			
			
		case 'w':  //forward                              
			fboffset = fboffset + 0.1;
			
			printf("fboffset =%.3f\n",fboffset);
			
			// send new turn value to ESP8266
			TCPSendBuffLen = sprintf(TCPSendBuff,"b%.5f\n",fboffset);
			  // Send the string to the server
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			break;
			
		case 's':  //backward                              
			fboffset = fboffset - 0.1;
			printf("fboffset =%.3f\n",fboffset);
			// send new turn value to ESP8266
			TCPSendBuffLen = sprintf(TCPSendBuff,"b%.5f\n",fboffset);
			  // Send the string to the server
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			break;	
			
		case 'r':  //reset direction of motion                              
			fboffset = 0.27;
			printf("fboffset =%.3f\n",fboffset);
			// send new turn value to ESP8266
			TCPSendBuffLen = sprintf(TCPSendBuff,"b%.5f\n",fboffset);
			  // Send the string to the server
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			break;	
		
			
		case 'e':
			inputdone = 1;
			break;
		case 'f':
			// request new Velocity reference point from user and send it to DSP
			printf("Enter Desired Velocity Setpoint\n");
			fgets(commandline,190,stdin); 
			sprintf(TCPSendBuff,"v%s\n",commandline);
			TCPSendBuffLen = strlen(TCPSendBuff);
			
			numBytes = send(sock, TCPSendBuff, TCPSendBuffLen, 0);
			if (numBytes < 0) {
				DieWithSystemMessage("send() failed");
			} else if (numBytes != TCPSendBuffLen) {
				DieWithUserMessage("send()", "sent unexpected number of bytes");
			}
			
			break;
		default:
			
			break;
		}
  }

 

  // Receive the same string back from the server
//  unsigned int totalBytesRcvd = 0; // Count of total bytes received
//  fputs("Received: ", stdout);     // Setup to print the echoed string
//  while (totalBytesRcvd < echoStringLen) {
//    char buffer[BUFSIZE]; // I/O buffer
    // Receive up to the buffer size (minus 1 to leave space for
    // a null terminator) bytes from the sender
//    numBytes = recv(sock, buffer, BUFSIZE - 1, 0);
//    if (numBytes < 0)
//      DieWithSystemMessage("recv() failed");
//    else if (numBytes == 0)
//      DieWithUserMessage("recv()", "connection closed prematurely");
//    totalBytesRcvd += numBytes; // Keep tally of total bytes
//    buffer[numBytes] = '\0';    // Terminate the string!
//    fputs(buffer, stdout);      // Print the buffer
//  }

  fputc('\n', stdout); // Print a final linefeed

  close(sock);
  exit(0);
}

int mygetch(void)
{
	struct termios oldt,
	newt;
	int ch;
	tcgetattr( STDIN_FILENO, &oldt );
	newt = oldt;
	newt.c_lflag &= ~( ICANON | ECHO );
	tcsetattr( STDIN_FILENO, TCSANOW, &newt );
	ch = getchar();
	tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
	return ch;
}

Code Composer Studio Zipped Project Files

C/C++
Entire CSS project
No preview (download only).

Credits

Nicholas Gustafson
1 project • 0 followers
Contact
Thanks to Dan Block.

Comments

Please log in or sign up to comment.