LP Long Distance IR Vision Robot

Dependencies:   max77650_charger_sample BufferedSerial SX1276GenericLib Adafruit-MotorShield NEO-6m-GPS MAX17055_EZconfig Adafruit_GFX USBDeviceHT Adafruit-PWM-Servo-Driver

main.cpp

Committer:
walterluu
Date:
2021-12-29
Revision:
44:8be011a3fba0
Parent:
42:911770814147

File content as of revision 44:8be011a3fba0:

/*
 * For Wiring Instructions, please visit the link below:
 * https://www.hackster.io/DevinAlex64/getting-started-with-the-max32620fthr-and-lora-f9d8dd\
 */

/***************************************************************************
 * Misc Instantiation
 **************************************************************************/\
#include "mbed.h"
#include "main.h"
#include "global_buffers.h"
//#define DEBUG_GRID_EYE
//#define DEBUG_MAX17055
#define RASPBERRY_PI
#define NUM_TIMEOUTS_TO_STOP_ROBOT 15
#define OLED_FREQ 1000

DigitalOut myled(LED);
Serial pc(USBTX, USBRX);

I2C i2cBus0(P1_6, P1_7);            // I2CM0 of MAX32620FTHR
I2C i2cBus1(P3_4, P3_5);            // I2CM1 of MAX32630FTHR
I2C i2cBus2(P5_7, P6_0);            // I2CM2 to BMI160 of MAX32630FTHR

/***************************************************************************
 * MAX32630FTHR Instantiation
 **************************************************************************/
#if defined(TARGET_MAX32630FTHR) 
    /* If the board that is compiled is the master device (BLE enabled MAX32630FTHR),
     * then it needs this library and needs to be configed in order for the device to 
     * work with a 3.3volt output instead of a 1.8 volt output. 
     * 
     * This is only needed for the MAX32630FTHR. The MAX325620FTHR is exampt from this 
     * additional setup in the main program.
     */ 
    #include "max32630fthr.h"
    MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
#endif

/***************************************************************************
 * MAX32620FTHR Instantiation
 **************************************************************************/
#if defined(TARGET_MAX32620FTHR)

#endif


/***************************************************************************
 * Grid Eye Sensor Instantiation
 **************************************************************************/
#include "GridEye.h"

#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    /* No grid eye object needed. The function the master uses to convert the raw 
     * data that is sent over from the slave deevice that contains the data from the
     * actual grid eye sensor is actually a function that is not part of the grid eye
     * class. this is due to the fact that the grid eye class requires n i2c bus to 
     * be assigned to a phyiscal sensor. In this case, the library for the Grid Eye 
     * sensor has a support function that is used to convert data that is aquired from 
     * the grid eye sensor. So it is not supposed to be a class specific function.
     */
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    GridEye gridEye(i2cBus0);
#endif

/***************************************************************************
 * GPS Instantiation
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    // No GPS module on the master device
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    #include "GPS.h"
    GPS gps(P0_1, P0_0, 115200); // (Tx, Rx, Baud rate)
#endif

/***************************************************************************
 * MAX77650 Instatiation
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    // No MAX77650 PMIC on this board
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    #include "max77650.h" 
    
    // Definitions for running board off of battery
    #define POWER_HOLD_ON 1
    #define POWER_HOLD_OFF 0
    
    /* This is the pin that the MAX77650's Power Hold pin is connected to on MAX32620FTHR
     * Without programming it to POWER_HOLD_ON, the device cant be started off of battery
     * power alone.
     */
    DigitalOut pw_Hold(P2_2, POWER_HOLD_ON);
    
    // Instatiate instance of the Simo Pimic 
    MAX77650 simo_pmic(i2cBus2);
    
    // Battery Charger Interrupt
    InterruptIn simoIRQ(P2_3);
    
    void charger_Detect();
    bool chrg_State_fn();
#endif

 
/***************************************************************************
 * MAX17055 Instatiation
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    // No MAX77650 PMIC on this board
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    #include "max17055.h"
    
    MAX17055 fuelGauge(i2cBus2);
    MAX17055::platform_data design_param; 
    
#endif


/***************************************************************************
 * OLED Instatiation
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    #include "Adafruit_SSD1306.h"
    #include "maxim_bitmap.h"
    Adafruit_SSD1306_I2c displayOled(i2cBus1);
    

#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    /* Currently, there is no OLED display attached to the MAX32620,
     * so we are not compiling for it at the moment
     */
#endif


/***************************************************************************
 * BLE Instatiation and Related Functions
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    #include "ble/BLE.h"
    //#include "ble/Gap.h"
    #include "UARTService_custom.h"
    #include <events/mbed_events.h>
    
    DigitalOut led2(LED2);
    UARTService *uart;
    
    #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
                                   * it will have an impact on code-size and power consumption. */
 
    #if NEED_CONSOLE_OUTPUT
    #define DEBUG(STR) { if (uart) uart->write(STR, strlen(STR)); }
    #define READ(STR) { if (uart) uart->read(STR, strlen(STR)); }
    
    #else
    #define DEBUG(...) /* nothing */
    #endif /* #if NEED_CONSOLE_OUTPUT */
    
    //Triggered when the robot is disconnected from the mobile app.
    void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
    {
        BLE &ble = BLE::Instance();
        DEBUG("Disconnected!\n\r");
        DEBUG("Restarting the advertising process\n\r");
        ble.gap().startAdvertising();
    }
    
    /* This pointer is needed to reference data in the main program when filling 
     * with data from the BLE 
     */
    uint8_t * onDataWritten_curr_ble_to_slave;
    
    // Triggered when there is data written
    void onDataWritten(const GattWriteCallbackParams *params)
    {    
        //LED1 will be off when button is pressed, and on when button is released.
        led2 = !led2;
        uint8_t button_state;
        uint8_t direction;

        /* If there is a valid data sent by the mobile app */
        if ((uart != NULL) && (params->handle == uart ->getTXCharacteristicHandle())) {
            const uint8_t *packet = params->data;
            button_state = packet[3];
            direction = packet[2];
    
            // make parameter to send over Lora        
            onDataWritten_curr_ble_to_slave[0] = direction;
            onDataWritten_curr_ble_to_slave[1] = button_state;
            
            //dprintf("direction: %d\n", direction);
            //dprintf("button_state: %d\n", button_state);      
        }
    }
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    // No BLE chip on the MAX32620FTHR so this is not needed
#endif
 
/***************************************************************************
 * Motor Controller Instatiation and Related Functions
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    // There is no motor controller on this device.
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    /* This is a port of a library that was developed by Adafruit for the Arduino. 
     * This port was done by mbed user syundo0730. */
    #include "Adafruit_MotorShield.h"
    #include "Adafruit_PWMServoDriver.h"
    
    // These are the defined speeds that are selected out of the number range (0, 255).
    #define MOTOR_OFF 0
    #define MOTOR_FORWARD 150
    #define MOTOR_BACKWARD 150
    #define MOTOR_TURN 100
    
    // Create the motor shield object with the default I2C address
    Adafruit_MotorShield AFMS = Adafruit_MotorShield(P3_4, P3_5, 0x60 << 1); // You have to shift it over by one due to how mbed does its I2C Addressing. 
    // Or, create it with a different I2C address (say for stacking)
    // Adafruit_MotorShield AFMS = Adafruit_MotorShield(P3_4, P3_5, 0x61 << 1); 
    // Select which 'port' M1, M2, M3 or M4. In this case, M1
    Adafruit_DCMotor *rightMotor = AFMS.getMotor(1);
    // You can also make another motor on port M4
    Adafruit_DCMotor *leftMotor = AFMS.getMotor(4);
    
    
    void MotorController(uint8_t (BLE_data_server)[2])
    {
        uint8_t button_state;
        uint8_t direction;
        /*Set up constants for direction of motion */
        const char FRONT = '5';
        const char BACK = '6';
        const char LEFT = '7';
        const char RIGHT = '8';
        
        /*Set up constants for button state */
        const char PRESSED = '1';
        const char RELEASED = '0';
        
    
        button_state = BLE_data_server[1];
        direction = BLE_data_server[0];
        
        switch (button_state)
        {
            case PRESSED:
                switch (direction)
                {
                    case FRONT:
                        rightMotor->run(FORWARD);
                        leftMotor->run(FORWARD);
                        rightMotor->setSpeed(MOTOR_FORWARD);
                        leftMotor->setSpeed(MOTOR_FORWARD);
                        break;
                    case BACK:
                        rightMotor->run(BACKWARD);
                        leftMotor->run(BACKWARD);
                        rightMotor->setSpeed(MOTOR_BACKWARD);
                        leftMotor->setSpeed(MOTOR_BACKWARD);
                        break;
                    case LEFT:
                        rightMotor->run(FORWARD);
                        leftMotor->run(BACKWARD);
                        rightMotor->setSpeed(MOTOR_TURN);
                        leftMotor->setSpeed(MOTOR_TURN);
                        break;
                    case RIGHT:
                        rightMotor->run(BACKWARD);
                        leftMotor->run(FORWARD);
                        rightMotor->setSpeed(MOTOR_TURN);
                        leftMotor->setSpeed(MOTOR_TURN);
                        break;
                }      
                break;
            case RELEASED:
                rightMotor->setSpeed(MOTOR_OFF);
                leftMotor->setSpeed(MOTOR_OFF);
                break;
        }
    }
#endif






int main() 
{
    /* Setup begins here: */
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        dprintf("MAX32630FTHR: Master");
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        dprintf("MAX32620FTHR: Slave");
    #endif
    

    #if defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        //Set Power Hold High for battery operation MAX77650 on MAX32620FTHR
        pw_Hold = POWER_HOLD_ON; 
    #endif    
    
    /*
     * inits the Serial or USBSerial when available (230400 baud).
     * If the serial uart is not is not connected it swiches to USB Serial
     * blinking LED means USBSerial detected, waiting for a connect.
     * It waits up to 30 seconds for a USB terminal connections 
     */
    InitSerial(30*1000, &myled);
    dprintf("Welcome to the SX1276GenericLib");
  
    dprintf("Starting a simple LoRa PingPong");
    
    
    /***************************************************************************
     * Grid Eye Sensor: Non-Buffer Program Variables
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        int frame_idx = 0;
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        #if defined(DEBUG_GRID_EYE_SLAVE)
            int frame_idx = 0;
        #endif
    #endif
    
    
    /***************************************************************************
     * Combined Payload Buffers for LoRa Communications
     **************************************************************************/
    uint8_t BufferTx[BufferSizeTx];
    uint8_t BufferRx[BufferSizeRx];
    
    /***************************************************************************
     * Identification Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        uint8_t ID_of_slave[size_signature]; 
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        uint8_t ID_of_master[size_signature];
    #endif
    
    /***************************************************************************
     * BLE Data Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        uint8_t curr_ble_to_slave[size_of_ble]; 
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        uint8_t curr_ble_from_master[size_of_ble];
        uint8_t prev_ble_from_master[size_of_ble];
    #endif
    
    /***************************************************************************
     * Grid Eye Sensor Data Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        char curr_raw_frame_from_slave[size_of_grid_eye];
        char prev_raw_frame_from_slave[size_of_grid_eye];
        int16_t conv_frame_from_slave[64];
    #elif defined(TARGET_MAX32620FTHR) // Client Device: LoRa Controlled Robot
        char curr_raw_frame_to_master[size_of_grid_eye];
        char prev_raw_frame_to_master[size_of_grid_eye];
        int16_t conv_frame_to_master[64];
    #endif
    
    /***************************************************************************
     * GPS Data Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        uint8_t curr_gps_from_slave[size_of_gps];
        uint8_t prev_gps_from_slave[size_of_gps];
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        uint8_t curr_gps_to_master[size_of_gps];
    #endif
    
    /***************************************************************************
     * MAX17055 Data Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        union max17055_u
        {   
            uint8_t curr_MAX17055_from_slave[size_of_MAX17055];
            struct battery
            {
                uint8_t soc_FG;         // in Battery Percent
                uint8_t avg_soc_FG;     // in Battery Percent
                float tte_FG;           // in seconds
                float ttf_FG;           // in seconds
                int vcell_FG;              // in 78.125uV per bit
                int curr_FG;               // in uAmps
                int avg_curr_FG;           // in uAmps                
            } battery;
        } max17055_u;
        uint8_t prev_MAX17055_from_slave[size_of_MAX17055];
        
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        union max17055_u
        {   
            uint8_t curr_MAX17055_to_master[size_of_MAX17055];
            struct battery
            {
                uint8_t soc_FG;         // in Battery Percent
                uint8_t avg_soc_FG;     // in Battery Percent
                float tte_FG;           // in seconds
                float ttf_FG;           // in seconds
                int vcell_FG;              // in 78.125uV per bit
                int curr_FG;               // in uAmps
                int avg_curr_FG;           // in uAmps                
            } battery;
        } max17055_u;
    #endif
    
    /***************************************************************************
     * MAX77650 Data Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        uint8_t curr_MAX77650_from_slave[size_of_MAX77650];
        uint8_t prev_MAX77650_from_slave[size_of_MAX77650];
        bool chrg_status = false;; //True = ON False = OFF    
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        uint8_t curr_MAX77650_to_master[size_of_MAX77650];
        bool chrg_status = false; //True = ON False = OFF
    #endif

    
    /***************************************************************************
     * Finish Setting up LoRa Radios: This passes in pointers to Buffers to send
     **************************************************************************/
    SX1276PingPongSetup(BufferTx, BufferRx);
    
    /***************************************************************************
     * Finish Setting up BLE Radio on the MAX32630FTHR: Only on the Master Device
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        BLE &ble = BLE::Instance();
        /* Create alias for the BLE data to be saved in function above that 
         * writes data to this buffer when function onDataWritten is called 
         */
        onDataWritten_curr_ble_to_slave = curr_ble_to_slave;
        
        /* Initialize BLE */
        ble.init();
        ble.gap().onDisconnection(disconnectionCallback);
        ble.gattServer().onDataWritten(onDataWritten);
        uart = new UARTService(ble);
        /* setup advertising */
        ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
        ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
        ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                         (const uint8_t *)"BLE UART", sizeof("BLE UART") - 1);
        ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                         (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
        ble.gap().setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
        ble.gap().startAdvertising();
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        /* There is no BLE device that is integrated into the MAX32620FTHR. Also
         * Also this program is meant to use the BLE gateway on the MAX32630FTHR 
         */
    #endif
    
    /***************************************************************************
     * Finish Setting up the MAX77650 on the MAX32620FTHR: Only on the Slave Device
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        // No MAX77650 on the MAX32630FTHR
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        //Set Power Hold High for battery operation MAX77650 on MAX32620FTHR
        pw_Hold = POWER_HOLD_ON; 
        //Simo Pmic MAX77650 init
        simo_pmic.initCharger();
        simoIRQ.fall( &charger_Detect );
        simo_pmic.enCharger();
    #endif
    /***************************************************************************
     * Finish Setting up the MAX17650 on the MAX32620FTHR: Only on the Slave Device
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        // No MAX17055 on the MAX32630FTHR
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    //rsense 5mOhm for MAX32620FTHR
        design_param.designcap = 2200;  //Design Battery Capacity mAh
        design_param.ichgterm = 0x0016;  // Charge Termination Current for the Battery
        design_param.vempty = 0x9B00;  // Battery Empty Voltage
        design_param.vcharge = 4200;  // Battery Charge Voltage can be obtained from MAX77650 configuration
        design_param.rsense = 5; //5mOhms
    
        int oper_f1, volt_mod_FG;
        int status; // stores return value of the status of setting up the MAX17055
        
        //serial.printf("Test Init and Temp Functions \r\n");
        //status = fuelGauge.forcedExitHyberMode();
        status = fuelGauge.init(design_param);
        pc.printf("Init FuelGauge Function Status= %X \r\n",status);
    #endif
    
    /***************************************************************************
     * Finish Setting up the SSD1306 OLED on the MAX32630FTHR: Only on the Master Device
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        displayOled.setTextColor(1);
        displayOled.setTextSize(1);
        displayOled.setTextWrap(false);
    
        displayOled.clearDisplay();
        displayOled.printf("%ux%u Please Check Connection to Robot!!\r\n", displayOled.width(), displayOled.height());
        //displayOled.drawBitmap(0,0,maximLarge,128,32,1);
        displayOled.display();
        displayOled.display();
        wait(1.0);
    
        displayOled.startscrollright(0x00, 0x0F);
        
        
        uint32_t OLED_COUNT;
        
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        // No oled on the MAX32620FTHR
    #endif
    
    /***************************************************************************
     * Finish Setting up the motor controller on the MAX32620FTHR: Only on the Slave Device
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        // No setup on the master device
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        AFMS.begin();  // create with the default frequency 1.6KHz
        //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
      
        // Set the speed to start, from 0 (off) to 255 (max speed)
        rightMotor->setSpeed(150);
        rightMotor->run(FORWARD);
        // turn on motor
        rightMotor->run(RELEASE);
        
        leftMotor->setSpeed(150);
        leftMotor->run(FORWARD);
        // turn on motor
        leftMotor->run(RELEASE);
    #endif
    
    
    while(1) 
    {       
        /***************************************************************************
         * BLE Radio Data 
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            ble.waitForEvent();
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            memcpy(curr_ble_from_master, prev_ble_from_master, sizeof(curr_ble_from_master));
        #endif
        
        /***************************************************************************
         * Grid Eye Sensor 
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            // Check to see if the contents of the previous scan are the same. If they are different then continue with converting
            #if defined(RASPBERRY_PI)
                if( memcmp(prev_raw_frame_from_slave, curr_raw_frame_from_slave, sizeof(curr_raw_frame_from_slave)) != 0 )
                {
                    char grid_eye_msg[130];
                    grid_eye_msg[0]=0x55;
                    grid_eye_msg[1]=0xaa;
                    for (int idx = 0; idx < 128; idx++)
                        grid_eye_msg[idx+2] = curr_raw_frame_from_slave[idx];
                    //pc.printf(grid_eye_msg);
                    for (int idx = 0; idx < 130; idx++)
                    pc.putc(grid_eye_msg[idx]);
                    pc.printf("\r\n"); // seperate the lines
                }
            #endif
            #if defined(DEBUG_GRID_EYE)
                if( memcmp(prev_raw_frame_from_slave, curr_raw_frame_from_slave, sizeof(curr_raw_frame_from_slave)) != 0 )
                {
                    // Convert raw data sent from slave to a 16 bit integer array by calling this
                    convRaw8x8Data2Point25degC(curr_raw_frame_from_slave, conv_frame_from_slave);
                    
                    // Next Print off the Converted data
                    pc.printf("\r\nFrame %d data: \r\n", frame_idx);
                    uint8_t idx;
                    float pixel_data;
                    for (int y = 0; y < 8; y++) {
                        for (int x = 0; x < 8; x++) {
                            idx = y*8 + x;
                            pixel_data = ((float)conv_frame_from_slave[idx])/4.0;
                            pc.printf("%.2f  \t", pixel_data);
                        }
                        pc.printf("\r\n\r\n");
                    }
                    pc.printf("\r\n");
                    
                    // Increment frame counter
                    frame_idx = frame_idx +1;
                }
            #endif    
                /* Next copy in data received from current data into buffer used for
                 * comparison next time the memcmp above is called. This prevents the 
                 * program from converting the same raw data aquired by the grid eye
                 * sensor on the slave device to the floating point array with the 
                 * 0.25 degrees celsius precision level when there is not new data. 
                 */

            memcpy(prev_raw_frame_from_slave, curr_raw_frame_from_slave, sizeof(curr_raw_frame_from_slave));
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            // Aquire raw data about 8x8 frame from the grid eye sensor in this function call 
            gridEye.getRaw8x8FrameData(curr_raw_frame_to_master);
            #if defined(RASPBERRY_PI)
                if( memcmp(prev_raw_frame_to_master, curr_raw_frame_to_master, sizeof(curr_raw_frame_to_master)) != 0 )
                {
                    char grid_eye_msg[130];
                    grid_eye_msg[0]=0x55;
                    grid_eye_msg[1]=0xaa;
                    for (int idx = 0; idx < 128; idx++)
                        grid_eye_msg[idx+2] = curr_raw_frame_to_master[idx];
                    //pc.printf(grid_eye_msg);
                    for (int idx = 0; idx < 130; idx++)
                    pc.putc(grid_eye_msg[idx]);
                    pc.printf("\r\n"); // seperate the lines
                }
            #endif
            #if defined(DEBUG_GRID_EYE)
                if( memcmp(prev_raw_frame_to_master, curr_raw_frame_to_master, sizeof(curr_raw_frame_to_master)) != 0 )
                {
                    // Convert raw data sent from slave to a 16 bit integer array by calling this
                    convRaw8x8Data2Point25degC(curr_raw_frame_to_master, conv_frame_to_master);
                    
                    
                    // Next Print off the Converted data
                    pc.printf("\r\nFrame %d data: \r\n", frame_idx);
                    uint8_t idx;
                    float pixel_data;
                    for (int y = 0; y < 8; y++) {
                        for (int x = 0; x < 8; x++) {
                            idx = y*8 + x;
                            pixel_data = ((float)conv_frame_to_master[idx])/4.0;
                            pc.printf("%.2f  \t", pixel_data);
                        }
                        pc.printf("\r\n\r\n");
                    }
                    pc.printf("\r\n");
                    
                    // Increment frame counter
                    frame_idx = frame_idx +1;
                }
            #endif
            memcpy(prev_raw_frame_to_master, curr_raw_frame_to_master, sizeof(curr_raw_frame_to_master));
        #endif      
        
        /***************************************************************************
         * GPS Sensor 
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            // No gps sensor is applied
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            // The testing hasnt been done yet for the GPS Module. Will do this when more parts come in. 
            /*
            if(gps.sample()){
              pc.printf("%f\t%c\t%f\t%c\t%f\t%f\t%f\n\r",gps.longitude, gps.ns,gps.latitude,gps.ew, gps.alt, gps.geoid, gps.time);
              pc.printf("%d:%d:%d",gps.hour,gps.minute,gps.seconed);
            }
            */
        #endif
        
        /***************************************************************************
         * MAX17055 Fuel Gauge Sensor 
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            // Process the soc to see if the oled display needs to be updated or not.
            #if defined(DEBUG_MAX17055)
                pc.printf("soc_FG :%d\n"      ,max17055_u.battery.soc_FG);
                pc.printf("avg_soc_FG :%d\n"  ,max17055_u.battery.avg_soc_FG);
                pc.printf("tte_FG :%d\n"      ,max17055_u.battery.tte_FG);
                pc.printf("ttf_FG :%d\n"      ,max17055_u.battery.ttf_FG);
                pc.printf("vcell_FG :%d\n"    ,max17055_u.battery.vcell_FG);
                pc.printf("curr_FG :%d\n"     ,max17055_u.battery.curr_FG);
                pc.printf("avg_curr_FG :%d\n" ,max17055_u.battery.avg_curr_FG);
                
                for (int idx = 0; idx < size_of_MAX17055; idx++)
                {
                    pc.printf("Byte #%d is: %d\n", idx, max17055_u.curr_MAX17055_from_slave[idx]);
                }
            #endif
            OLED_COUNT = OLED_COUNT + 1;
            if( OLED_COUNT % OLED_FREQ == 0) {
                if( memcmp(prev_MAX17055_from_slave, curr_MAX17055_from_slave, sizeof(curr_MAX17055_from_slave)) != 0 )
                {
                    // Stop the scrolling to allow for a static image to be displayed on OLED
                    displayOled.stopscroll();
                    
                    displayOled.clearDisplay();
    
//                    if ( chrg_status == false){
//                        if (max17055_u.battery.soc_FG >= 89)
//                            displayOled.drawBitmap(96,0,battFull,32,16,1);
//                        else if (max17055_u.battery.soc_FG >= 65 && max17055_u.battery.soc_FG < 89)
//                            displayOled.drawBitmap(96,0,batt75,32,16,1);
//                        else if (max17055_u.battery.soc_FG >= 45 && max17055_u.battery.soc_FG < 65)
//                            displayOled.drawBitmap(96,0,batt50,32,16,1);
//                        else if (max17055_u.battery.soc_FG >= 20 && max17055_u.battery.soc_FG < 45)
//                            displayOled.drawBitmap(96,0,batt25,32,16,1);
//                        else 
//                            displayOled.drawBitmap(96,0,battEmpty,32,16,1);
//                    }
    
                    if (chrg_status == true){
                        displayOled.drawBitmap(96,0,battChrging,32,16,1);
                    }
    
                    
                    //serial.printf("Time to Empty= %dsec \r\n",tte_FG);
                    int tte_minutes = (max17055_u.battery.tte_FG/60);
                    int ttf_minutes = (max17055_u.battery.tte_FG/60);
                    //serial.printf("Time to Empty= %dhours \r\n",tte_FG); 
                    //serial.printf("Temp Function Status= %X \r\n",status);
                    //wait(1);
                    //serial.printf("SOC = %d %% \r\n",soc_FG);
                    //serial.printf("Temp Function Status= %X \r\n",status);
                    //serial.printf("Current = %d uamp \r\n",curr_FG);
    //                pc.printf("Voltage = %d uvolts \r\n",max17055_u.battery.vcell_FG);
                    int oper_f1 = max17055_u.battery.vcell_FG /1000000;
                    int volt_mod_FG = (max17055_u.battery.vcell_FG % 1000000)/1000;
    
    //                pc.printf("Voltage = %d V \r\n",max17055_u.battery.vcell_FG);
    //                pc.printf("Voltage = %d V \r\n",oper_f1);
    
    
    
                    displayOled.setTextCursor(0,0);
                    displayOled.setTextColor(1);
                    displayOled.setTextSize(1);
                    //displayOled.setTextWrap(true);
                    displayOled.printf("MAX17055");
                    displayOled.setTextCursor(0,8);
                    displayOled.printf("SOC = %d%% \r\n",max17055_u.battery.avg_soc_FG);
                
                    displayOled.setTextCursor(0,16);
                    if (chrg_status == true){    
                        displayOled.printf("TTF = %dmins \r\n",tte_minutes);
                    }else 
                        displayOled.printf("TTE = %dmins \r\n",tte_minutes);
                    displayOled.setTextCursor(0,24);
//                    displayOled.printf("I=%dmA \r\n",max17055_u.battery.avg_curr_FG/1000);
//                    displayOled.setTextCursor(65,24);
                    if (volt_mod_FG > 99){
                        displayOled.printf("V=%d.%dV \r\n",oper_f1,volt_mod_FG);
                    }else if (volt_mod_FG < 100){
                        displayOled.printf("V=%d.0%dV \r\n",oper_f1,volt_mod_FG);   
                    }
                    
                    displayOled.display();
                    displayOled.display();            
                }
            }
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot    
            max17055_u.battery.soc_FG      = fuelGauge.get_SOC();
            max17055_u.battery.avg_soc_FG  = fuelGauge.get_atAvSOC(); 
            max17055_u.battery.tte_FG      = fuelGauge.get_TTE();
            max17055_u.battery.ttf_FG      = fuelGauge.get_TTF();
            max17055_u.battery.vcell_FG    = fuelGauge.get_Vcell();
            max17055_u.battery.curr_FG     = fuelGauge.get_Current(design_param);
            max17055_u.battery.avg_curr_FG = fuelGauge.get_AvgCurrent(design_param);
            
            #if defined(DEBUG_MAX17055)
                pc.printf("soc_FG :%d\n"      ,max17055_u.battery.soc_FG);
                pc.printf("avg_soc_FG :%d\n"  ,max17055_u.battery.avg_soc_FG);
                pc.printf("tte_FG :%d\n"      ,max17055_u.battery.tte_FG);
                pc.printf("ttf_FG :%d\n"      ,max17055_u.battery.ttf_FG);
                pc.printf("vcell_FG :%d\n"    ,max17055_u.battery.vcell_FG);
                pc.printf("curr_FG :%d\n"     ,max17055_u.battery.curr_FG);
                pc.printf("avg_curr_FG :%d\n" ,max17055_u.battery.avg_curr_FG);
                
                for (int idx = 0; idx < size_of_MAX17055; idx++)
                {
                    pc.printf("Byte #%d is: %d\n", idx, max17055_u.curr_MAX17055_to_master[idx]);
                }
            #endif
        #endif
        
        /***************************************************************************
         * Fill Payload Buffer With Data From Main Program Buffers for next LoRa Transmition
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            memcpy(&BufferTx[tx_idx_signature], PingMsg,           size_signature);
            memcpy(&BufferTx[tx_idx_ble],       curr_ble_to_slave, size_of_ble);
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            memcpy(&BufferTx[tx_idx_signature], PongMsg,                  size_signature);
            memcpy(&BufferTx[tx_idx_grid_eye],  curr_raw_frame_to_master, size_of_grid_eye);
            memcpy(&BufferTx[tx_idx_gps],       curr_gps_to_master,       size_of_gps);
            memcpy(&BufferTx[tx_idx_MAX17055],  max17055_u.curr_MAX17055_to_master,  size_of_MAX17055);
            memcpy(&BufferTx[tx_idx_MAX77650],  curr_MAX77650_to_master,  size_of_MAX77650);
        #endif
        

        /***************************************************************************
         * Lora Communications
         **************************************************************************/
        SX1276PingPong();           // what changes here?
        
        /***************************************************************************
         * Fill Main Program Buffers With Data From Received Payload Buffer
         **************************************************************************/
        /* The master and slave devices will have different requirements for offloading payload */
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            memcpy(ID_of_slave,               &BufferRx[rx_idx_signature], size_signature);
            memcpy(curr_raw_frame_from_slave, &BufferRx[rx_idx_grid_eye],  size_of_grid_eye);
            memcpy(curr_gps_from_slave,       &BufferRx[rx_idx_gps],       size_of_gps);
            memcpy(max17055_u.curr_MAX17055_from_slave,  &BufferRx[rx_idx_MAX17055],  size_of_MAX17055);
            memcpy(curr_MAX77650_from_slave,  &BufferRx[rx_idx_MAX77650],  size_of_MAX77650);
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            memcpy(ID_of_master,              &BufferRx[rx_idx_signature], size_signature);
            memcpy(curr_ble_from_master,      &BufferRx[rx_idx_ble],       size_of_ble);
        #endif
    
        /***************************************************************************
         * Motor Controller controlls go here
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            // No motor controller on master
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            /* This helps prevent devices such as robots that are connected over 
             * LoRa from not receiving a stop message. This can help prevent 
             * situations where a robot received a command to move in a dirrection
             * but then moved to an area where it cant reliably receive communications.
             * This situation would prevent a robot from stopping if it cant receive
             * communications. So this is used to stop the current movement if the 
             * robot is still moving after x amount of RxTimeouts have happened 
             * in the LoRa communications. 
             */
            if (numOfRxTimeouts() >= NUM_TIMEOUTS_TO_STOP_ROBOT)
            {
                uint8_t simulate_release_button[2];
                simulate_release_button[0] = curr_ble_from_master[0];
                simulate_release_button[1] = 0;
                MotorController(simulate_release_button);
            }
            
            // Check to see if the contents of the previous ble sdata received are the same. If they are different then change motor controllers registers
            else if( memcmp(prev_ble_from_master, curr_ble_from_master, sizeof(curr_ble_from_master)) != 0 )
            {
                MotorController(curr_ble_from_master);
                memcpy(prev_ble_from_master, curr_ble_from_master, sizeof(curr_ble_from_master));
            }
             
        #endif   
    }
}


/***************************************************************************
 * MAX77650 Additional Functions
 **************************************************************************/
#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
    // No MAX77650 PMIC on this board
#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
    void charger_Detect() 
    {
        uint8_t int_chr_value,temp, int_chr_MASK = 0x04;         
        int status; 
        pc.printf("Charger Detected \n");
        status = simo_pmic.readReg(MAX77650::INT_CHG, int_chr_value);
        pc.printf("INT_CHR val= %X  \n", int_chr_value);
        if (status == 1){
            temp = int_chr_value & int_chr_MASK;
            pc.printf("INT_CHR anded= %X  \n", temp);
            if (temp == 4) 
            {
                pc.printf("enable charger \n");
                simo_pmic.enCharger();
            }
        }
    }
    
    bool chrg_State_fn()
    {
        uint8_t status_chr_value,temp, chr_status_MASK = 0x02;         
        int status; 
        pc.printf("Charger State \n");
        status = simo_pmic.readReg(MAX77650::STAT_CHG_B, status_chr_value);
        pc.printf("STAR_CHG_B val= %X  \n", status_chr_value);
        if (status == 1)
        {
            temp = status_chr_value & chr_status_MASK;
            pc.printf("STAR_CHG_B val= %X  \n", temp);
            if (temp == 2){
                return true; 
            }
            return false; 
        }
        return false;
    }
    
#endif