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:
dev_alexander
Date:
2018-07-31
Revision:
34:f31a6b53d4ea
Parent:
33:52c898aca207

File content as of revision 34:f31a6b53d4ea:

/*
 * Copyright (c) 2018 HELIOS Software GmbH
 * 30826 Garbsen (Hannover) Germany
 * Licensed under the Apache License, Version 2.0);
 */
  
 /*
 * For Wiring Instructions, please visit the link below:
 * https://www.hackster.io/DevinAlex64/getting-started-with-the-max32620fthr-and-lora-f9d8dd\
 */
 
#include "main.h"
#include "global_buffers.h"
#include "GridEye.h"
#include "GPS.h"

#define RASPBERRY_PI

/* 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.
 */ 
 

/***************************************************************************
 * Create an instance of the MAX32630FTHR related Items.
 **************************************************************************/
#if defined(TARGET_MAX32630FTHR) 
    #include "max32630fthr.h"
    MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);

    
    
    /* BLE Related MAX32630FTHR Specific stuff */
    #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);      
    
        }
    }
#endif


/***************************************************************************
 * Create an instance of the Panasonic Grid Eye Sensor (AMG88xx)
 **************************************************************************/
#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 functin 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: Robot
    //Init I2C communications in default I2C bus I2C #1
    I2C i2cGridEye(P3_4,P3_5);
    GridEye gridEye(i2cGridEye);
#endif

/***************************************************************************
 * Create an instance of the Adafruit Ultimate GPS v3

 **************************************************************************/
#if defined(TARGET_MAX32620FTHR)
    GPS gps(P0_1, P0_0, 115200);
#endif

DigitalOut myled(LED);

Serial pc(USBTX, USBRX);

int main() 
{
    /*
     * 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");
    
    /* 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
    
    
    /***************************************************************************
     * 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
        // none yet
        int frame_idx = 0;
    #endif
    
    
    /***************************************************************************
     * Combined Payload Buffers for LoRa Communications
     **************************************************************************/
    uint8_t BufferTx[BufferSizeTx];
    uint8_t BufferRx[BufferSizeRx];
    
    /***************************************************************************
     * BLE Data Buffers
     **************************************************************************/
    #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
        uint8_t curr_ble_to_slave[size_of_ble]; 
        #if defined(COMPILE_BLE) 
            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();
        #endif
    #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
        uint8_t curr_MAX17055_from_slave[size_of_MAX17055];
        uint8_t prev_MAX17055_from_slave[size_of_MAX17055];
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        uint8_t curr_MAX17055_to_master[size_of_MAX17055];
    #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];
    #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
        uint8_t curr_MAX77650_to_master[size_of_MAX77650];
    #endif
    
    /***************************************************************************
     * Finish Setting up LoRa Radios: This passes in pointers to Buffers to send
     **************************************************************************/
    SX1276PingPongSetup(BufferTx, BufferRx);
    
    while(1) 
    {        
        /***************************************************************************
         * BLE Radio Data 
         **************************************************************************/
        #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
            #if defined(COMPILE_BLE) 
            ble.waitForEvent();
            #endif
        #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
            // NOTHING YET
        #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 )
                {
                    /*
                    //for (int idx = 0; idx < 8; idx++)
                    //    pc.printf("%c", ID_of_slave[idx]);
                    string grid_eye_msg;
                    grid_eye_msg[0]=0x55;
                    grid_eye_msg[1]=0xaa;
                    for (int idx = 0; idx < 128; idx++)
                        grid_eye_msg[idx+2] = (unsigned char)curr_raw_frame_from_slave[idx];
                    pc.printf(grid_eye_msg);
                    */
                    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]);
                }
            #else
                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);
            wait_ms( 20 );
            
            #if defined(DEBUG_GRID_EYE_SLAVE)
                if( memcmp(prev_raw_frame_to_master, curr_raw_frame_to_master, sizeof(curr_raw_frame_to_master)) != 0 )
                {
                    wait_ms( 5 );
                    // 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);
                    
                    wait_ms( 5 );
                    
                    // 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
            #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]);
                }
            #endif
            wait_ms( 20 );
            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
            //None yet
        #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
        
        /***************************************************************************
         * Fill Payload Buffer With Data From Sensors for 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],  curr_MAX17055_to_master,  size_of_MAX17055);
            memcpy(&BufferTx[tx_idx_MAX77650],  curr_MAX77650_to_master,  size_of_MAX77650);
        #endif
        
        
        
        /***************************************************************************
         * Lora Communications
         **************************************************************************/
        wait_ms( 10 );  
        SX1276PingPong();
        
        /***************************************************************************
         * Fill Global 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(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(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(curr_ble_from_master,      &BufferRx[rx_idx_ble],      size_of_ble);
        #endif
    
        
        
        
        
    }
    
}