This is example code that can get you started with building your own IR vision robot that communicates over LoRa
Dependencies: Adafruit-MotorShield Adafruit-PWM-Servo-Driver Adafruit_GFX BufferedSerial MAX17055_EZconfig NEO-6m-GPS SX1276GenericLib USBDeviceHT max32630fthr max77650_charger_sample
Fork of MAX326xxFTHR_LoRa_Example_test by
GenericPingPong.cpp
00001 /* 00002 * This file contains a copy of the master content sx1276PingPong 00003 * with adaption for the SX1276Generic environment 00004 * (c) 2017 Helmut Tschemernjak 00005 * 30826 Garbsen (Hannover) Germany 00006 */ 00007 00008 #include "mbed.h" 00009 #include "PinMap.h" 00010 #include "GenericPingPong.h" 00011 #include "sx1276-mbed-hal.h" 00012 #include "main.h" 00013 #include "global_buffers.h" 00014 00015 #ifdef FEATURE_LORA 00016 00017 /* Set this flag to '1' to display debug messages on the console */ 00018 #define DEBUG_MESSAGE 0 00019 00020 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */ 00021 #define USE_MODEM_LORA 1 00022 #define USE_MODEM_FSK !USE_MODEM_LORA 00023 #define RF_FREQUENCY RF_FREQUENCY_915_0 // Hz 00024 #define TX_OUTPUT_POWER 14 // 14 dBm 00025 00026 #if USE_MODEM_LORA == 1 00027 00028 #define LORA_BANDWIDTH 125000 // LoRa default, details in SX1276::BandwidthMap 00029 #define LORA_SPREADING_FACTOR LORA_SF7 00030 #define LORA_CODINGRATE LORA_ERROR_CODING_RATE_4_5 00031 00032 #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 00033 #define LORA_SYMBOL_TIMEOUT 5 // Symbols 00034 #define LORA_FIX_LENGTH_PAYLOAD_ON false 00035 #define LORA_FHSS_ENABLED false 00036 #define LORA_NB_SYMB_HOP 4 00037 #define LORA_IQ_INVERSION_ON false 00038 #define LORA_CRC_ENABLED true 00039 00040 #elif USE_MODEM_FSK == 1 00041 00042 #define FSK_FDEV 25000 // Hz 00043 #define FSK_DATARATE 19200 // bps 00044 #define FSK_BANDWIDTH 50000 // Hz 00045 #define FSK_AFC_BANDWIDTH 83333 // Hz 00046 #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx 00047 #define FSK_FIX_LENGTH_PAYLOAD_ON false 00048 #define FSK_CRC_ENABLED true 00049 00050 #else 00051 #error "Please define a modem in the compiler options." 00052 #endif 00053 00054 00055 //#define RX_TIMEOUT_VALUE 3500 // in ms 00056 #define RX_TIMEOUT_VALUE 333 // in ms 00057 00058 00059 //#define BUFFER_SIZE 64 // Define the payload size here 00060 00061 /* 00062 * Global variables declarations 00063 */ 00064 typedef enum 00065 { 00066 LOWPOWER = 0, 00067 IDLE, 00068 00069 RX, 00070 RX_TIMEOUT, 00071 RX_ERROR, 00072 00073 TX, 00074 TX_TIMEOUT, 00075 00076 CAD, 00077 CAD_DONE 00078 } AppStates_t; 00079 00080 volatile AppStates_t State = LOWPOWER; 00081 00082 /*! 00083 * Radio events function pointer 00084 */ 00085 static RadioEvents_t RadioEvents; 00086 00087 /* 00088 * Global variables declarations 00089 */ 00090 SX1276Generic *Radio; 00091 00092 00093 // Aliases for the buffers that are made in the main() 00094 uint8_t *BufferTx; 00095 uint8_t *BufferRx; 00096 00097 DigitalOut *led3; 00098 00099 00100 int SX1276PingPongSetup(uint8_t *BufferTxFromMain, uint8_t *BufferRxFromMain) 00101 { 00102 dprintf("TEST" ); 00103 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) ) 00104 DigitalOut *led = new DigitalOut(LED2); 00105 #elif defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_DISCO_L072CZ_LRWAN1) 00106 DigitalOut *led = new DigitalOut(LED4); // RX red 00107 led3 = new DigitalOut(LED3); // TX blue 00108 #else 00109 DigitalOut *led = new DigitalOut(LED1); 00110 led3 = led; 00111 #endif 00112 00113 BufferTx = BufferTxFromMain; 00114 BufferRx = BufferRxFromMain; 00115 *led3 = 1; 00116 00117 #ifdef B_L072Z_LRWAN1_LORA 00118 Radio = new SX1276Generic(NULL, MURATA_SX1276, 00119 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00120 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, 00121 LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO); 00122 #else // RFM95 00123 Radio = new SX1276Generic(NULL, RFM95_SX1276, 00124 LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, 00125 LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5); 00126 00127 #endif 00128 00129 dprintf("SX1276 Ping Pong Demo Application" ); 00130 dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0); 00131 dprintf("TXPower: %d dBm", TX_OUTPUT_POWER); 00132 #if USE_MODEM_LORA == 1 00133 dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH); 00134 dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR); 00135 #elif USE_MODEM_FSK == 1 00136 dprintf("Bandwidth: %d kHz", FSK_BANDWIDTH); 00137 dprintf("Baudrate: %d", FSK_DATARATE); 00138 #endif 00139 // Initialize Radio driver 00140 RadioEvents.TxDone = OnTxDone; 00141 RadioEvents.RxDone = OnRxDone; 00142 RadioEvents.RxError = OnRxError; 00143 RadioEvents.TxTimeout = OnTxTimeout; 00144 RadioEvents.RxTimeout = OnRxTimeout; 00145 if (Radio->Init( &RadioEvents ) == false) { 00146 while(1) { 00147 dprintf("Radio could not be detected!"); 00148 wait( 1 ); 00149 } 00150 } 00151 00152 00153 switch(Radio->DetectBoardType()) { 00154 case SX1276MB1LAS: 00155 if (DEBUG_MESSAGE) 00156 dprintf(" > Board Type: SX1276MB1LAS <"); 00157 break; 00158 case SX1276MB1MAS: 00159 if (DEBUG_MESSAGE) 00160 dprintf(" > Board Type: SX1276MB1LAS <"); 00161 case MURATA_SX1276: 00162 if (DEBUG_MESSAGE) 00163 dprintf(" > Board Type: MURATA_SX1276_STM32L0 <"); 00164 break; 00165 case RFM95_SX1276: 00166 if (DEBUG_MESSAGE) 00167 dprintf(" > HopeRF RFM95xx <"); 00168 break; 00169 default: 00170 dprintf(" > Board Type: unknown <"); 00171 } 00172 00173 Radio->SetChannel(RF_FREQUENCY ); 00174 00175 #if USE_MODEM_LORA == 1 00176 00177 if (LORA_FHSS_ENABLED) 00178 dprintf(" > LORA FHSS Mode <"); 00179 if (!LORA_FHSS_ENABLED) 00180 dprintf(" > LORA Mode <"); 00181 00182 00183 // Without this line, the default max payload length is only 64 bytes 00184 Radio->SetMaxPayloadLength(MODEM_LORA, 255); 00185 00186 Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, 00187 LORA_SPREADING_FACTOR, LORA_CODINGRATE, 00188 LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, 00189 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00190 LORA_IQ_INVERSION_ON, 2000 ); 00191 00192 Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, 00193 LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, 00194 LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, 00195 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00196 LORA_IQ_INVERSION_ON, true ); 00197 00198 #elif USE_MODEM_FSK == 1 00199 00200 dprintf(" > FSK Mode <"); 00201 Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, 00202 FSK_DATARATE, 0, 00203 FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, 00204 FSK_CRC_ENABLED, 0, 0, 0, 2000 ); 00205 00206 Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 00207 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, 00208 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, 00209 0, 0, false, true ); 00210 00211 #else 00212 00213 #error "Please define a modem in the compiler options." 00214 00215 #endif 00216 00217 if (DEBUG_MESSAGE) 00218 dprintf("Starting Ping-Pong loop"); 00219 00220 00221 Radio->Rx( RX_TIMEOUT_VALUE ); 00222 } 00223 00224 /**************************************************************************************************************************************** 00225 * 00226 ****************************************************************************************************************************************/ 00227 int SX1276PingPong(void) 00228 { 00229 #if defined(TARGET_MAX32630FTHR) // Master Device: Bluetooth Gateway 00230 bool isMaster = true; 00231 #elif defined(TARGET_MAX32620FTHR) // Slave Device: Robot 00232 bool isMaster = false; 00233 #endif 00234 00235 switch( State ) 00236 { 00237 case RX: 00238 // *led3 = 0; 00239 if( isMaster == true ) 00240 { 00241 if( BufferSizeRx > 0 ) 00242 { 00243 /* This checks if the ID of the received transaction is matching that of 00244 * the slave device's ID. This is Defined in the GenericPingPong.h 00245 */ 00246 if( memcmp(&BufferRx[rx_idx_signature], PongMsg, sizeof(PongMsg)) == 0 ) 00247 { 00248 // *led = !*led; 00249 if (DEBUG_MESSAGE) 00250 dprintf( "...Pong" ); 00251 wait_ms( 10 ); 00252 Radio->Send( BufferTx, BufferSizeTx ); 00253 } 00254 else // valid reception but neither a PING or a PONG message 00255 { // Set device as master ans start again 00256 //isMaster = true; 00257 Radio->Rx( RX_TIMEOUT_VALUE ); 00258 } 00259 } 00260 } 00261 else 00262 { 00263 if( BufferSizeRx > 0 ) 00264 { 00265 if( memcmp(BufferRx, PingMsg, sizeof(PingMsg)) == 0 ) 00266 { 00267 // *led = !*led; 00268 if (DEBUG_MESSAGE) 00269 dprintf( "...Ping" ); 00270 wait_ms( 10 ); 00271 Radio->Send( BufferTx, BufferSizeTx ); 00272 } 00273 else // valid reception but not a PING as expected 00274 { // Set device as master and start again 00275 //isMaster = true; 00276 Radio->Rx( RX_TIMEOUT_VALUE ); 00277 } 00278 } 00279 } 00280 State = LOWPOWER; 00281 break; 00282 case TX: 00283 // *led3 = 1; 00284 if( isMaster == true ) 00285 { 00286 if (DEBUG_MESSAGE) 00287 dprintf("Ping..." ); 00288 } 00289 else 00290 { 00291 if (DEBUG_MESSAGE) 00292 dprintf("Pong..." ); 00293 } 00294 Radio->Rx( RX_TIMEOUT_VALUE ); 00295 State = LOWPOWER; 00296 break; 00297 case RX_TIMEOUT: 00298 if( isMaster == true ) 00299 { 00300 wait_ms( 10 ); 00301 Radio->Send( BufferTx, BufferSizeTx ); 00302 } 00303 else 00304 { 00305 Radio->Rx( RX_TIMEOUT_VALUE ); 00306 } 00307 State = LOWPOWER; 00308 break; 00309 case RX_ERROR: 00310 // We have received a Packet with a CRC error, send reply as if packet was correct 00311 if( isMaster == true ) 00312 { 00313 // Send the next PING frame 00314 // memcpy(BufferTx, PingMsg, sizeof(PingMsg)); 00315 /* 00316 for( i = 4; i < BufferSizeTx; i++ ) 00317 { 00318 BufferTx[i] = i - 4; 00319 } 00320 */ 00321 // fillPayloadWithGlobalBufs(BufferTx); 00322 wait_ms( 10 ); 00323 Radio->Send( BufferTx, BufferSizeTx ); 00324 } 00325 else 00326 { 00327 // Send the next PONG frame 00328 // memcpy(BufferTx, PongMsg, sizeof(PongMsg)); 00329 /* 00330 for( i = sizeof(PongMsg); i < BufferSizeTx; i++ ) 00331 { 00332 BufferTx[i] = i - sizeof(PongMsg); 00333 } 00334 */ 00335 wait_ms( 10 ); 00336 Radio->Send( BufferTx, BufferSizeTx ); 00337 } 00338 State = LOWPOWER; 00339 break; 00340 case TX_TIMEOUT: 00341 Radio->Rx( RX_TIMEOUT_VALUE ); 00342 State = LOWPOWER; 00343 break; 00344 case LOWPOWER: 00345 sleep(); 00346 break; 00347 default: 00348 State = LOWPOWER; 00349 break; 00350 } 00351 } 00352 00353 void OnTxDone(void *radio, void *userThisPtr, void *userData) 00354 { 00355 Radio->Sleep( ); 00356 State = TX; 00357 if (DEBUG_MESSAGE) 00358 dprintf("> OnTxDone"); 00359 } 00360 00361 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 00362 { 00363 Radio->Sleep( ); 00364 00365 if(BufferSizeRx != size) 00366 memcpy( BufferRx, payload, size ); 00367 else 00368 memcpy( BufferRx, payload, BufferSizeRx ); 00369 State = RX; 00370 00371 // Reset the RxTimeoutCount 00372 RxTimeoutCount = 0; 00373 00374 if (DEBUG_MESSAGE) { 00375 dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr); 00376 dump("Data:", payload, size); 00377 } 00378 } 00379 00380 void OnTxTimeout(void *radio, void *userThisPtr, void *userData) 00381 { 00382 // *led3 = 0; 00383 Radio->Sleep( ); 00384 State = TX_TIMEOUT; 00385 if(DEBUG_MESSAGE) 00386 dprintf("> OnTxTimeout"); 00387 } 00388 00389 void OnRxTimeout(void *radio, void *userThisPtr, void *userData) 00390 { 00391 // *led3 = 0; 00392 Radio->Sleep( ); 00393 BufferRx[BufferSizeRx-1] = 0; 00394 State = RX_TIMEOUT; 00395 if (DEBUG_MESSAGE) 00396 dprintf("> OnRxTimeout"); 00397 00398 // Increment how many times a transmission times out\ 00399 RxTimeoutCount = RxTimeoutCount + 1; 00400 } 00401 00402 void OnRxError(void *radio, void *userThisPtr, void *userData) 00403 { 00404 Radio->Sleep( ); 00405 State = RX_ERROR; 00406 if (DEBUG_MESSAGE) 00407 dprintf("> OnRxError"); 00408 00409 // Increment how many times a transmission times out\ 00410 RxTimeoutCount = RxTimeoutCount + 1; 00411 } 00412 00413 int numOfRxTimeouts() 00414 { 00415 return RxTimeoutCount; 00416 } 00417 00418 #endif
Generated on Tue Jul 26 2022 05:48:54 by 1.7.2