TX

Dependencies:   mbed BufferedSerial SX1276GenericLib X_NUCLEO_IKS01A2

main.cpp

Committer:
TMRL123
Date:
2019-06-05
Revision:
4:a0cfe0efcc5e
Parent:
0:a73914f20498

File content as of revision 4:a0cfe0efcc5e:

/* Includes */
#include "mbed.h" /* Mbed include */

#include "XNucleoIKS01A2.h" /* Sensors include*/

/* LoRa includes */
#include "PinMap.h" 
#include "sx1276-mbed-hal.h" 

/* Serial communication include */
#include "BufferedSerial.h"

/* LoRa definitions */

/* Set this flag to '1' to display debug messages on the console */
#define DEBUG_MESSAGE   1

/* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
#define USE_MODEM_LORA  1
#define USE_MODEM_FSK   !USE_MODEM_LORA
#define RF_FREQUENCY            RF_FREQUENCY_915_0  // Hz
#define TX_OUTPUT_POWER         14                  // 14 dBm

#if USE_MODEM_LORA == 1

#define LORA_BANDWIDTH          125000  // LoRa default, details in SX1276::BandwidthMap
#define LORA_SPREADING_FACTOR   LORA_SF7
#define LORA_CODINGRATE         LORA_ERROR_CODING_RATE_4_5

#define LORA_PREAMBLE_LENGTH    8       // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT     5       // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON  false
#define LORA_FHSS_ENABLED       false  
#define LORA_NB_SYMB_HOP        4     
#define LORA_IQ_INVERSION_ON    false
#define LORA_CRC_ENABLED        true
    
#endif 


#define RX_TIMEOUT_VALUE    0       // In ms
#define TX_TIMEOUT_VALUE    1000000 // In ms

//#define BUFFER_SIZE       32        // Define the payload size here
#define BUFFER_SIZE         64        // Define the payload size here

/* Sensors instances */

/* Instantiate the expansion board */
static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);

/* Retrieve the composing elements of the expansion board */
static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;

typedef struct {
            float p; // Pressure
            float temperatureHTS221; // Temperature from HTS221
            float humidity; // Humidity
            float temperatureLPS22HB; // Temperature from LPS22HB
            int32_t w[3]; // Angular velocity
            int32_t a[3]; // Acceleration of the accelerometer LSM303AGR
            int32_t ag[3]; // Acceleration of the accelerometer and gyroscope LSM6DSL 
            int32_t m [3]; // Heading 
}Data; // Data struct
        
Data data;

/* LoRa modem instances and configurations */

static RadioEvents_t RadioEvents; // Calback functions struct

SX1276Generic *Radio; // Defenition of a Radio object

/* Configuration function */
void SystemClock_Config(void);

bool transmited = true;// Flag to indicate the and of transmission

/* Callback functions prototypes */

// Brief Function to be executed on Radio Tx Done event
void OnTxDone(void *radio, void *userThisPtr, void *userData);

// Brief Function to be executed on Radio Rx Done event
void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );

// Brief Function executed on Radio Tx Timeout event
void OnTxTimeout(void *radio, void *userThisPtr, void *userData);

// Brief Function executed on Radio Rx Timeout event
void OnRxTimeout(void *radio, void *userThisPtr, void *userData);

// Brief Function executed on Radio Rx Error event
void OnRxError(void *radio, void *userThisPtr, void *userData);

// Brief Function executed on Radio Fhss Change Channel event
void OnFhssChangeChannel(void *radio, void *userThisPtr, void *userData, uint8_t channelIndex);

/* Serial communication to debug program */
BufferedSerial *ser;

int main() {
    SystemClock_Config(); /* Synchronize clock for TX and RX boards*/
    
    /* Serial configuration */
    if (DEBUG_MESSAGE) {
        ser = new BufferedSerial(USBTX, USBRX);
        ser->baud(115200);
        ser->format(8);
    }
        
    /* General Header*/
    if (DEBUG_MESSAGE)
        ser->printf("Telemetry Rx inicial version program\r\n\r\n");
    
    uint8_t id; //Sensor id parameter for debug purpose
    
    /* Enable all sensors */
    hum_temp->enable();
    press_temp->enable();
    magnetometer->enable();
    accelerometer->enable();
    acc_gyro->enable_x();
    acc_gyro->enable_g();
    
    if (DEBUG_MESSAGE) {  
        ser->printf("\r\n--- Starting the sensors ---\r\n");
        
        hum_temp->read_id(&id);
        ser->printf("HTS221  humidity & temperature    = 0x%X\r\n", id);
        press_temp->read_id(&id);
        ser->printf("LPS22HB  pressure & temperature   = 0x%X\r\n", id);
        magnetometer->read_id(&id);
        ser->printf("LSM303AGR magnetometer            = 0x%X\r\n", id);
        accelerometer->read_id(&id);
        ser->printf("LSM303AGR accelerometer           = 0x%X\r\n", id);
        acc_gyro->read_id(&id);
        ser->printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id);
        
        ser->printf("\r\n");
    }
    /* Radio setup */
    if (DEBUG_MESSAGE)
        ser->printf("\r\n--- Starting the modem LoRa ---\r\n");
    
    Radio = new SX1276Generic(NULL, MURATA_SX1276,
            LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
            LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
            LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
    if (DEBUG_MESSAGE) {
        ser->printf("SX1276 Simple transmission aplication\r\n" );
        ser->printf("Frequency: %.1f\r\n", (double)RF_FREQUENCY/1000000.0);
        ser->printf("TXPower: %d dBm\r\n",  TX_OUTPUT_POWER);
        ser->printf("Bandwidth: %d Hz\r\n", LORA_BANDWIDTH);
        ser->printf("Spreading factor: SF%d\r\n", LORA_SPREADING_FACTOR);
    }
    // Initialize Radio driver
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.RxError = OnRxError;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout; 
    
    while (Radio->Init( &RadioEvents ) == false) {
        if (DEBUG_MESSAGE)
            ser->printf("Radio could not be detected!\r\n");
        wait( 1 );
    }
    
    // Display the board type
    switch(Radio->DetectBoardType()) {
        case SX1276MB1LAS:
            if (DEBUG_MESSAGE)
                ser->printf(" > Board Type: SX1276MB1LAS <\r\n");
            break;
        case SX1276MB1MAS:
            if (DEBUG_MESSAGE)
                ser->printf(" > Board Type: SX1276MB1LAS <\r\n");
        case MURATA_SX1276:
            if (DEBUG_MESSAGE)
                ser->printf(" > Board Type: MURATA_SX1276_STM32L0 <\r\n");
            break;
        case RFM95_SX1276:
            if (DEBUG_MESSAGE)
                ser->printf(" > HopeRF RFM95xx <\r\n");
            break;
        default:
            if (DEBUG_MESSAGE)
                ser->printf(" > Board Type: unknown <\r\n");
    }
    
    Radio->SetChannel(RF_FREQUENCY ); // Sets the frequency of the communication
    
    // Debug message of the state of fhss
    if (LORA_FHSS_ENABLED) {
        if (DEBUG_MESSAGE)
            ser->printf("             > LORA FHSS Mode <\r\n");
    }    
    if (!LORA_FHSS_ENABLED) {
        if (DEBUG_MESSAGE)
            ser->printf("             > LORA Mode <\r\n");
    }
    
    // Sets the configuration of the transmission    
    Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                         LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                         LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                         LORA_IQ_INVERSION_ON, 2000 );
    
    // Sets the configuration of the reception
    Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                         LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                         LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                         LORA_IQ_INVERSION_ON, true );
      
    Radio->Tx(TX_TIMEOUT_VALUE); // Puts the device in transmission mode for a long period
    
    while(1) {   
    
        press_temp->get_pressure(&data.p); // Get the pressure
        press_temp->get_temperature(&data.temperatureLPS22HB); // Get temperature from LPS22HB
        accelerometer->get_x_axes(data.a);// Get the acceleration
        acc_gyro->get_x_axes(data.ag);// Get the acceleration
        acc_gyro->get_g_axes(data.w);// Get the angular velocity
        magnetometer->get_m_axes(data.m); // Get the magnetometer heading
        hum_temp->get_temperature(&data.temperatureHTS221); // Get temperature from HTS221
        hum_temp->get_humidity(&data.humidity); // Get humidity
        
        // Only sends a new packet when the device already have transmited the previous one 
        if (transmited==true) {
            transmited = false;
            wait_ms(10);
            Radio->Send( &data, sizeof(data) );
        }
    }
}

void SystemClock_Config(void)
{
#ifdef B_L072Z_LRWAN1_LORA
    /* 
     * The L072Z_LRWAN1_LORA clock setup is somewhat differnt from the Nucleo board.
     * It has no LSE.
     */
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};

    /* Enable HSE Oscillator and Activate PLL with HSE as source */
    RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSEState            = RCC_HSE_OFF;
    RCC_OscInitStruct.HSIState            = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI;
    RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLLMUL_6;
    RCC_OscInitStruct.PLL.PLLDIV          = RCC_PLLDIV_3;

    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        // Error_Handler();
    }

    /* Set Voltage scale1 as MCU will run at 32MHz */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */
    while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {};

    /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
    clocks dividers */
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
        // Error_Handler();
    }
#endif
}

/* Helper function for printing floats & doubles */


void OnTxDone(void *radio, void *userThisPtr, void *userData)
{   
    Radio->Sleep( );
    transmited = true;
    if (DEBUG_MESSAGE) {
        ser->printf("> OnTxDone\r\n");
        ser->printf("I transmited %d mg, %d mg, %d mg, %d mg, %d mg, %d mg, %d mdps, %d mdps, %d mdps\r\n", data.a[0], data.a[1], data.a[2], data.ag[0], data.ag[1], data.ag[2], data.w[0], data.w[1], data.w[2]);
        ser->printf("and %d mG, %d mG, %d mG, %g %%, %g C, %g C, %g mBar\r\n", data.m[0], data.m[1], data.m[2], data.humidity, data.temperatureHTS221, data.temperatureLPS22HB, data.p);
    }    
}

void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    Radio->Sleep( );
    if (DEBUG_MESSAGE)
        ser->printf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d\r\n", rssi, snr);
}

void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
{
    Radio->Sleep( );
    if(DEBUG_MESSAGE)
        ser->printf("> OnTxTimeout\r\n");
}

void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
{
    Radio->Sleep( );
    if (DEBUG_MESSAGE)
        ser->printf("> OnRxTimeout\r\n");
}

void OnRxError(void *radio, void *userThisPtr, void *userData)
{
    Radio->Sleep( );
    if (DEBUG_MESSAGE)
        ser->printf("> OnRxError\r\n");
}