Justin Schubeck
Published

Texas Instruments RSLK / MeArm

Control a 4 degrees of freedom robotic clamping arm over Wi-Fi using the TI RSLK and two MSP432s!

AdvancedWork in progressOver 1 day189
Texas Instruments RSLK / MeArm

Things used in this project

Story

Read more

Schematics

MG90S Servo Documentation

The PWM signal needed for the MeArm servo is documented in this file.

MSP432P401 Datasheet

In accordance with MSP432 needs.

MSP432P4xx Technical Reference Manual

In accordance with MSP432 needs.

CC3100 SimpleLink Wi-Fi Boosterpack Datasheet

In accordance with CC3100 needs.

CC3100 SimpleLink Wi-Fi Boosterpack User's Guide

In accordance with CC3100 needs.

Code

main.c

C/C++
Main file to configure both host and client.
#include <G8RTOS.h>
#include <driverlib.h>
#include "BSP.h"
#include "i2c_driver.h"
#include "BoardSupportPackage\inc\Clock.h"


/* Client Threads */
extern void JoinGame();
extern void ReceiveDataFromHost();
extern void UpdatePWM();

/* Host Threads */
extern void CreateGame();
extern void SendDataToClient();
extern void ReadJoystickHost();

/* Shared Threads */
extern void IdleThread();

/* Helper Functions */
extern playerType GetPlayerRole();

/* Prevent Interruptions */
extern semaphore_t WifiMutex;

void main(void)
{
    /* Initialize The Board And Peripherals */
    /* Disable Watchdog */
    WDT_A_clearTimer();
    WDT_A_holdTimer();

    /* Initialize Clock And Timer */
    Clock_Init48MHz();

    /* Init i2c */
    initI2C();

    /* Initialize The RTOS And Semaphores */
    G8RTOS_Init();
    G8RTOS_InitSemaphore(&WifiMutex, 1);

    /* Decide Which User We Are */
    playerType role = GetPlayerRole();

    /* Connect The Users And Initialize WiFi Accordingly */
    initCC3100(role);

    /* Add Correct Starting Thread */
    if(role == Host){G8RTOS_AddThread(CreateGame, 1, "Create Game");}
    else if(role == Client){G8RTOS_AddThread(JoinGame, 1, "Join Game");}

    /* Launch The RTOS */
    G8RTOS_Launch();
    while(1);
}

RTOS Threads Header

C/C++
Header for the threads to control Wi-Fi and PWM.
#ifndef ROBOT_H_
#define ROBOT_H_

/*********************************************** Includes ********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "G8RTOS_Lab5/G8RTOS.h"
#include "CC3100SupportPackage\cc3100_usage\cc3100_usage.h"
/*********************************************** Includes ********************************************************************/

/*********************************************** Externs ********************************************************************/
extern semaphore_t WifiMutex;
/*********************************************** Externs ********************************************************************/

/*********************************************** Global Defines ********************************************************************/
/* Used as status LEDs for Wi-Fi */
#define RED_LED_ON    P2->OUT  |= 1
#define RED_LED_OFF   P2->OUT  &= ~1
#define GREEN_LED_ON  P2->OUT  |= 2
#define GREEN_LED_OFF P2->OUT  &= ~2
#define BLUE_LED_ON   P2->OUT  |= 4
#define BLUE_LED_OFF  P2->OUT  &= ~4
#define ALL_LEDS_OFF  P2->OUT  &= ~7
#define ALL_LEDS_ON   P2->OUT  |= 7

typedef enum
{
    BASE = 0,
    UPDOWN = 1,
    FORWARDBACK = 2,
    CLAW = 3
}controlType;
/*********************************************** Global Defines ********************************************************************/

/*********************************************** Data Structures ********************************************************************/
#pragma pack ( push, 1)
/*
 * Struct to be sent from the client to the host
 */
typedef struct
{
    uint32_t IP_address;
    bool joined;
    bool acknowledge;
} DeviceInfo_t;

/*
 * Struct to be sent from the host to the client
 */
typedef struct
{
    uint8_t mode;
    uint16_t pulse;
} State_t;
#pragma pack ( pop )
/*********************************************** Data Structures ********************************************************************/


/*********************************************** Client Threads *********************************************************************/
/*
 * Thread for client to join game
 */
void JoinGame();

/*
 * Thread that receives game state packets from host
 */
void ReceiveDataFromHost();

/*
 * Updates the PWM pulses of all motors.
 */
void UpdatePWM();
/*********************************************** Client Threads *********************************************************************/


/*********************************************** Host Threads *********************************************************************/
/*
 * Thread for the host to create a game
 */
void CreateGame();

/*
 * Thread that sends game state to client
 */
void SendDataToClient();


/*
 * Thread to read host's joystick
 */
void ReadJoystickHost();

/*
 * APERIODIC
 * ISR For New Game Button
 * Should Just Set A Flag Saying A Touch Occurred
 */
//void ButtonTap4();
//void ButtonTap5();

/*********************************************** Host Threads *********************************************************************/


/*********************************************** Common Threads *********************************************************************/
/*
 * Idle thread
 */
void IdleThread();
/*********************************************** Common Threads *********************************************************************/


/*********************************************** Public Functions *********************************************************************/
/*
 * Returns either Host or Client depending on button press
 */
playerType GetPlayerRole();
/*********************************************** Public Functions *********************************************************************/

#endif /* ROBOT_H_ */

RTOS Threads Source

C/C++
Threads to run on respective device.
#include <G8RTOS.h>
#include <G8RTOS_Scheduler.h>

/* Struct For Host To Hold Game Data */
State_t data = {0, 200};

/* Struct For Client To Hold Its Personal Data */
DeviceInfo_t clientInfo = {0, false, false};

/* JoyStick Coordinates */
int16_t X, Y;
int16_t delta = 0;

/* Pulses */
uint16_t Base = 200;
uint16_t UpDown = 200;
uint16_t ForwardBack = 200;
uint16_t Claw = 200;

/* Mutexes For Both Host And Client To Update */
semaphore_t WifiMutex;

/*********************************************** Client Threads *********************************************************************/
/*
 * Thread for client to join game
 */
void JoinGame()
{
    /* Initialize Client */
    clientInfo.IP_address = getLocalIP();

    /* Send Player To The Host */
    _i32 returnVal = -1;
    while((returnVal == -1) || (clientInfo.acknowledge == false))
    {
        clientInfo.acknowledge = true;
        SendData((uint8_t *) &clientInfo, HOST_IP_ADDR, sizeof(clientInfo));
        clientInfo.acknowledge = false;
        returnVal = ReceiveData((uint8_t *) &clientInfo, sizeof(clientInfo));
    }

    /* Join Game */
    clientInfo.joined = true;
    SendData((uint8_t *)&clientInfo, HOST_IP_ADDR, sizeof(clientInfo));

    /* If Joined, Acknowledge Joined To Host And Show Connection With Blue LED */
    RED_LED_OFF;
    BLUE_LED_ON;

    /* PWM Pin 7.4 */
    P7->SEL0 &= ~BIT4;
    P7->SEL1 &= ~BIT4;
    P7->DIR  |=  BIT4;
    P7->OUT  &= ~BIT4;

    /* PWM Pin 7.5 */
    P7->SEL0 &= ~BIT5;
    P7->SEL1 &= ~BIT5;
    P7->DIR  |=  BIT5;
    P7->OUT  &= ~BIT5;

    /* PWM Pin 7.6 */
    P7->SEL0 &= ~BIT6;
    P7->SEL1 &= ~BIT6;
    P7->DIR  |=  BIT6;
    P7->OUT  &= ~BIT6;

    /* PWM Pin 7.7 */
    P7->SEL0 &= ~BIT7;
    P7->SEL1 &= ~BIT7;
    P7->DIR  |=  BIT7;
    P7->OUT  &= ~BIT7;

    /* Add Starting Threads */
    G8RTOS_AddThread(ReceiveDataFromHost, 4, "Receive Data");
    G8RTOS_AddThread(UpdatePWM, 3, "Receive Data");
    G8RTOS_AddThread(IdleThread, 255, "Idle");

    /* Kill Self */
    G8RTOS_KillSelf();
}

/*
 * Thread that receives game state packets from host
 */
void ReceiveDataFromHost()
{
    while(1)
    {
        data.pulse = 150;
        /* Receive Updated Mode And Pulse Number */
        _i32 returnVal = -1;
        while(returnVal == -1)
        {
            G8RTOS_WaitSemaphore(&WifiMutex);
            returnVal = ReceiveData((uint8_t *) &data, sizeof(data));
            G8RTOS_SignalSemaphore(&WifiMutex);
            sleep(2);
        }
        /* Save Packet */
        if(data.mode == BASE)
        {
            Base = data.pulse;
        }
        else if(data.mode == UPDOWN)
        {
            UpDown = data.pulse;
        }
        else if(data.mode == FORWARDBACK)
        {
            ForwardBack = data.pulse;
        }
        else if(data.mode == CLAW)
        {
            Claw = data.pulse;
        }
    }
}

/*
 * Updates the PWM pulses of all motors.
 */
void UpdatePWM()
{
    uint16_t iBase, iUpDown, iForwardBack, iClaw = 0;
    uint16_t jBase, jUpDown, jForwardBack, jClaw = 0;
    while(1)
    {
        G8RTOS_WaitSemaphore(&WifiMutex);
        if(data.mode == BASE)
        {
            P7->OUT  |= BIT4;
            jBase = Base;
            for(iBase = 0; iBase < 3400 + jBase; iBase++);
            P7->OUT  &= ~BIT4;
            G8RTOS_SignalSemaphore(&WifiMutex);
            sleep(10);
        }
        else if(data.mode == UPDOWN)
        {
            P7->OUT  |= BIT5;
            jUpDown = UpDown;
            for(iUpDown = 0; iUpDown < 3400 + jUpDown; iUpDown++);
            P7->OUT  &= ~BIT5;
            G8RTOS_SignalSemaphore(&WifiMutex);
            sleep(10);
        }
        else if(data.mode == FORWARDBACK)
        {
            P7->OUT  |= BIT6;
            jForwardBack = ForwardBack;
            for(iForwardBack = 0; iForwardBack < 3400 + jForwardBack; iForwardBack++);
            P7->OUT  &= ~BIT6;
            G8RTOS_SignalSemaphore(&WifiMutex);
            sleep(10);
        }
        else if(data.mode == CLAW)
        {
            P7->OUT  |= BIT7;
            jClaw = Claw;
            for(iClaw = 0; iClaw < 3400 + jClaw; iClaw++);
            P7->OUT  &= ~BIT7;
            G8RTOS_SignalSemaphore(&WifiMutex);
            sleep(10);
        }
    }
}
/*********************************************** Client Threads *********************************************************************/


/*********************************************** Host Threads *********************************************************************/
/*
 * Thread for the host to create a game.
 * Only Thread Created Before Launching OS
 */
void CreateGame()
{
    /* Wait For Client To Sent Specific Player Information */
    _i32 returnVal = -1;
    while((returnVal == -1) || (clientInfo.acknowledge == false))
    {
        returnVal = ReceiveData((uint8_t *)&clientInfo, sizeof(clientInfo));
    }

    /* Acknowledge That We Have Connected With Client */
    SendData((uint8_t *)&clientInfo, clientInfo.IP_address, sizeof(clientInfo));
    clientInfo.acknowledge = false;

    /* Wait For Client To Join */
    returnVal = -1;
    while((returnVal == -1) || (clientInfo.joined == false))
    {
        returnVal = ReceiveData((uint8_t *)&clientInfo, sizeof(clientInfo));
    }

    /* Blue LED Indicating Good Connection */
    RED_LED_OFF;
    BLUE_LED_ON;

    /* Initialize Buttons */
    P4->DIR &= ~BIT4;
    P4->REN |= BIT4;
    P4->OUT |= BIT4;

    P4->DIR &= ~BIT5;
    P4->REN |= BIT5;
    P4->OUT |= BIT5;

    P5->DIR &= ~BIT4;
    P5->REN |= BIT4;
    P5->OUT |= BIT4;

    P5->DIR &= ~BIT5;
    P5->REN |= BIT5;
    P5->OUT |= BIT5;

    /* Init joystick without interrupts */
    Joystick_Init_Without_Interrupt();

    /* Add Starting Threads */
    G8RTOS_AddThread(ReadJoystickHost, 5, "JoyStick");
    G8RTOS_AddThread(SendDataToClient, 5, "Send Data");
    G8RTOS_AddThread(IdleThread, 255, "Idle");

    /* Kill Self */
    G8RTOS_KillSelf();
}

/*
 * Thread that sends game state to client
 */
void SendDataToClient()
{
    while(1)
    {
        /* Fill And Send Packet For Client */
        SendData((uint8_t *)&data, clientInfo.IP_address, sizeof(data));

        /* Sleep For 25ms (Experimentally For Synchronization) */
        //sleep(5);
    }
}

/*
 * Thread to read host's joystick
 */
void ReadJoystickHost()
{
    uint16_t pos = 0;
    while(1)
    {
        /* Read Buttons */
        if(!(P4->IN & BIT4)){data.mode = CLAW;}
        if(!(P4->IN & BIT5)){data.mode = FORWARDBACK;}
        if(!(P5->IN & BIT4)){data.mode = BASE;}
        if(!(P5->IN & BIT5)){data.mode = UPDOWN;}

        /* Read Joystick Coordinates */
        GetJoystickCoordinates(&X, &Y);

        /* Update PWM */
        if(data.mode == BASE)
        {
            pos = Base;
            delta = X / 1000;
            if(((int16_t)pos >= (delta * -1)) && (((int16_t)pos + delta) <= 3400))
            {
                pos += delta;
                Base = pos;
            }
        }
        else if(data.mode == UPDOWN)
        {
            pos = UpDown;
            delta = Y / -1000;
            if(((int16_t)pos >= (delta * -1)) && (((int16_t)pos + delta) <= 3400))
            {
                pos += delta;
                UpDown = pos;
            }
        }
        else if(data.mode == FORWARDBACK)
        {
            pos = ForwardBack;
            delta = Y / -1000;
            if(((int16_t)pos >= (delta * -1)) && (((int16_t)pos + delta) <= 3400))
            {
                pos += delta;
                ForwardBack = pos;
            }
        }
        else if(data.mode == CLAW)
        {
            pos = Claw;
            delta = X / -1000;
            if(((int16_t)pos >= (delta * -1)) && (((int16_t)pos + delta) <= 3400))
            {
                pos += delta;
                Claw = pos;
            }
        }

        data.pulse = pos;
        sleep(2);
    }
}
/*********************************************** Host Threads *********************************************************************/


/*********************************************** Common Threads *********************************************************************/
/*
 * Idle thread
 */
void IdleThread()
{
    while(1);
}
/*********************************************** Common Threads *********************************************************************/

/*********************************************** Public Functions *********************************************************************/
/*
 * Returns either Host or Client depending on button press
 */
playerType GetPlayerRole()
{
    /* Initialize Top Button S1 P1.1 For Client */
    P1->DIR &= ~BIT1;
    P1->REN |= BIT1;
    P1->OUT |= BIT1;

    /* Initialize Bottom Button S2 P1.4 For Host */
    P1->DIR &= ~BIT4;
    P1->REN |= BIT4;
    P1->OUT |= BIT4;

    /* Initialize WiFi Connection LEDs For Both Roles */
    P2->SEL1 &= ~7;
    P2->SEL0 &= ~7;
    P2->DIR  |= 7;
    ALL_LEDS_OFF;
    RED_LED_ON;

    while(1)
    {
        if(!(P1->IN & BIT1)){return Client;}
        if(!(P1->IN & BIT4)){return Host;}
    }
}
/*********************************************** Public Functions *********************************************************************/

Credits

Justin Schubeck
1 project • 0 followers
Contact

Comments

Please log in or sign up to comment.