LoRa点对点通信,OLED显示(内附代码)

时间:2022-07-25
本文章向大家介绍LoRa点对点通信,OLED显示(内附代码),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言:在上一节的基础上,为了方便测试,对PingPong通信进行改造,加入OLED显示,显示接收、发送数据包的个数和显示接收数据包的RSSI和SNR,一目了然。(视频演示:LoRa点对点通信演示

1、关于RSSI和SNR

RSSI:是Received Signal Strength Indication的缩写,中文含义是接收的信号强度指示,RSSI越大,表明信号越好。

SNR:是Signal Noise Ratio的缩写,中文含义是信噪比,是信号电平与噪声电平之比,SNR越大,表明信号越好。

2、实验设计

标定一个主机(M)一个从机(S),上电后主机主动发起通讯(发送“ping”),从机处于接收状态,从机接收到主机的信号后,回复信号(pong),完成一次正常通讯。在下一个发送点到来之前,主机都会一直等待从机的回复。下一个发送点到达之后发起下一次通讯。在整个通讯过程中从机不会主动发起通讯,只会在收到主机的信号后,回复主机信号。主从机的OLED会相应显示各自发送和接收到的包的个数和接收信号的RSSI和SNR。

3、代码实现

void MasterCycleSendTimerEvent()
{
  TimerStop(&MasterCycleSendTimer);

  Buffer[0] = 'P';
  Buffer[1] = 'I';
  Buffer[2] = 'N';
  Buffer[3] = 'G';
 
  for( i = 4; i < BufferSize; i++ )
  {
    Buffer[i] = i - 4;
  }
  DelayMs( 1 );
  printf("Send: PINGrn");
  Radio.Send( Buffer, BufferSize );
  
  TimerStart(&MasterCycleSendTimer);
}
//回调函数
void OnTxDone( void )
{
    Radio.Sleep( );
    
    TxCnt++;
    printf("Tx=%drn",TxCnt);
    
    memset(OLED_BUF,0,sizeof(OLED_BUF));
    if(isMaster)
    {
      sprintf(OLED_BUF,"M TX:%d  ",TxCnt);
    }
    else
    {
      sprintf(OLED_BUF,"S TX:%d  ",TxCnt);
    }
    OLED_ShowString(8,0,OLED_BUF,16);
    
    Radio.Rx( 0 );
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
    Radio.Sleep( );
    BufferSize = size;
    memcpy( Buffer, payload, BufferSize );
    RssiValue = rssi;
    SnrValue = snr;
    
    if( isMaster == true )
    {
       if( BufferSize > 0 )
       {
            if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
            {
                RxCnt++;
                memset(OLED_BUF,0,sizeof(OLED_BUF));
                sprintf(OLED_BUF,"RX:%d",RxCnt);
                OLED_ShowString(24,2,OLED_BUF,16);
                            
                memset(OLED_BUF,0,sizeof(OLED_BUF));
                sprintf(OLED_BUF,"Rssi:%d  ",RssiValue);
                OLED_ShowString(24,4,OLED_BUF,16);

                memset(OLED_BUF,0,sizeof(OLED_BUF));
                sprintf(OLED_BUF,"Snr:%d  ",SnrValue);
                OLED_ShowString(24,6,OLED_BUF,16);
                            
                printf("Received: PONG,rssi=%d,snr=%drn",RssiValue,SnrValue);
            }
            else
            {    
                Radio.Rx( 0 );
            }
        }
    }
    else
    {
        if( BufferSize > 0 )
        {
            if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
            {
                RxCnt++;
                memset(OLED_BUF,0,sizeof(OLED_BUF));
                sprintf(OLED_BUF,"RX:%d",RxCnt);
                OLED_ShowString(24,2,OLED_BUF,16);
                            
                memset(OLED_BUF,0,sizeof(OLED_BUF));
                sprintf(OLED_BUF,"Rssi:%d  ",RssiValue);
                OLED_ShowString(24,4,OLED_BUF,16);

                memset(OLED_BUF,0,sizeof(OLED_BUF));
                sprintf(OLED_BUF,"Snr:%d  ",SnrValue);
                OLED_ShowString(24,6,OLED_BUF,16);
                            
                printf("Received: PING,rssi=%d,snr=%drn",RssiValue,SnrValue);

                Buffer[0] = 'P';
                Buffer[1] = 'O';
                Buffer[2] = 'N';
                Buffer[3] = 'G';
                for( i = 4; i < BufferSize; i++ )
                {
                    Buffer[i] = i - 4;
                }
                DelayMs( 1 );
                Radio.Send( Buffer, BufferSize );
                printf("Send: PONGrn");
            }
            else 
            {   
                Radio.Rx( 0 );
            }
        }
    }
}

void OnTxTimeout( void )
{
    Radio.Sleep( );
    Radio.Rx( 0 );
}

void OnRxTimeout( void )
{
    printf("OnRxTimeoutrn");
    Radio.Sleep( );
    
    memset(OLED_BUF,0,sizeof(OLED_BUF));
    sprintf(OLED_BUF,"RX:%d",RxCnt);
    OLED_ShowString(24,2,OLED_BUF,16);
    
    Radio.Rx( 0 );
}

void OnRxError( void )
{
    Radio.Sleep( );
    
    Radio.Rx( 0 );
}

int main( void )
{
    BoardInitMcu( );
    printf("ASR6505 PingPong  test !rn");

    I2C_PeriphInit();
    BoardInitPeriph( );

    OLED_Init();
    OLED_Clear(); 
    OLED_ShowString(16,1,(char *)("LoRa"),16);
     
    OLED_ShowCN(48,1,0);
    OLED_ShowCN(64,1,1);
    OLED_ShowCN(80,1,2);
    OLED_ShowString(24,4,(char *)("ASR6505"),16);
    OLED_ShowString(8,6,(char *)("PingPong test"),16);

    Delay(3);
    OLED_Clear(); 
    memset(OLED_BUF,0,sizeof(OLED_BUF));

    // Radio initialization
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;
    RadioEvents.RxError = OnRxError;

    Radio.Init( &RadioEvents );

    Radio.SetChannel( RF_FREQUENCY );

    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                                   LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                                   LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );

    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                                   LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                                   LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
    if(isMaster)
    {
      TimerInit(&MasterCycleSendTimer,MasterCycleSendTimerEvent);
      TimerSetValue( &MasterCycleSendTimer, 5000 );
      TimerStart(&MasterCycleSendTimer);

      Buffer[0] = 'P';
      Buffer[1] = 'I';
      Buffer[2] = 'N';
      Buffer[3] = 'G';

      for( i = 4; i < BufferSize; i++ )
      {
          Buffer[i] = i - 4;
      }
      DelayMs( 1 );
      printf("Send: PINGrn");
      Radio.Send( Buffer, BufferSize );
      OLED_ShowString(8,0,"M",16);
    }
    else
    {
      Radio.Rx( 0 );
      OLED_ShowString(8,0,"S",16);
    }
    
    while( 1 )
    {
        Radio.IrqProcess( );
    }
}

4、实验现象

从图片中也可以清楚的看出,发送、接收、RSSI、SNR等重要参数,这些对于实际布网有重要意义。