User Tools

Site Tools


Sidebar

Modtronix.com
Sitemap

projects:arduino-lora-server-client1

Arduino + LoRa Server - Client

This is a simple example that explains how to connect the Arduino Pro Micro with the InAir4 module.

Updates

This code has been added to Modtronix GitHub. Please use this code for latest version, with bug fixes! https://github.com/modtronix-com/LoRa_inAir4_Client_Server

This Modtronix repository is based on the original code located here: check https://github.com/a3rd/lora-inair4

InAir4 Pinouts

The InAir4 module is manufactured by Modtronix, and with a Semtech SX1278 (SX1276) LoRa Module, set to 433MHz, 3.3V input, SMA Connector. Modtronix has a range of antennas that can be used with the LoRa module that are avialable as well.

http://modtronix.com/inair4.html

The pins are labelled as follows. Make sure that the model is inAir4 - this should be printed on the PCB.

Pin Pin
GND NC
CS 3.3V
DIO3 SCK
RST MISO
DIO0 MOSI
DIO1 NC
DIO2 VSWITCH

Pinout Description

GND Ground PIN
CS Chip Select
DIO3 Digital Input / Output (3)
RST Reset Pin
DIO0 Digital Input / Output (0)
DIO1 Digital Input / Output (1)
DIO2 Digital Input / Output (2)
NC Not Connected
3.3V Vin, 3.3VDC
SCK SPI Clock
MISO SPI MISO
MOSI SPI MOSI
NC Not Connected
VSWITCH VSWITCH

Module Image

1c1a8d3c-4263-11e5-8cd1-7023b1fc0c16.jpg

Bottom View

e834d1e4-4262-11e5-9c69-55152146cd1b.jpg

Pin Layout

Schematic

d29a771c-4262-11e5-85eb-6f83b0d87d32.jpg

Arduino Setup

Setting up the LoRa InAir4 Module with Arduino Pro Micro

The example code in this repo using GPIOs that can be configured accordingly, here we are using the Arduino Pro Micro.

To keep things simple the pins are wired as follows:

ProMicro () () ProMicro
GND GND NC
18 CS 3.3V 3.3VDC
? SCK SCK
21 RST MISO MISO
? MOSI MOSI
? NC
20 DIO2 VSWITCH 3.3VDC

This can be found in the example code where the pins are configured as follows:

SCK 	15
MOSI	16 
MISO	14
RESET 	21
DIO0 	20
NSEL    18
LED 	19	

Concept of Operation

There are two Arduino Pro Micros, each with a InAir4 module connected as per the pinouts above. One should be programmed as the lora-client and one should be programmed as the lora-server.

There are two ways to monitor the inAir4 modules, 1. Through the USB serial port, 9600 8N1 _or_ 2. Through the console port. This is using a USB ←→ 3.3V level cable, connected to pins 1,2 & GND

The code can be easily altered to have hte debug messages come to the _serial_ instead of the _console_ . A simple find and replace can make this change.

Registers

On power up there is some communication back and forth between the arduino and the inAir4. This can be used to confirm that the power is wired correctly and the SPI interface is functioning.

Config

sx1278_Config() sets all the registers as requried. Just about everything is fixed - including the frequency at 433Mhz. Before changing any settings its recommended that the two units are tested at short range with the default settings.

Setup

After config it goes to sx1278_Setup() which configures all the GPIO pins. This is self explanatory.

Loop

In the main loop the code will force the lora-client into RX_continuous mode, and the lora-server into TX mode. An arbitary message is loaded into the TX buffer that should be sent out the first time around then after a shortly delay the TX buffer is rewritten with the alphabest.

The contains of the opmode register and RX buffer are continually output, so all changes to the data transmission should be seen there.

Code: LoRa Client

lora_client.ino
/*************************************
Project: Pro Micro Arduino + LoRa iMod 4 Client
Data Rate : Determined by program
Frequency: 433Mhz
Modulation: LoRA
Transmit mode : continuous receive
*************************************/
 
#include <SoftwareSerial.h>
 
/*************************************
Software Serial Setup
Data Rate : 9600bps
Pinouts: RX -> TXO (pin 0), TX -> RX0, GNd -> GND
Transmit mode : continuous transmit
*************************************/
 
SoftwareSerial console(1, 0);    // RX, TX
 
 
unsigned char mode; //lora --1 / FSK --0
unsigned char Freq_Sel; //
unsigned char Power_Sel; //
unsigned char Lora_Rate_Sel; //
unsigned char BandWide_Sel; //
unsigned char Fsk_Rate_Sel; //
 
// Pinout for Arduino Pro Micro
 
int led = 19; 					// Pro Micro P19, A1, D14
int nsel = 18;					// Pro Micro P18, A0, 	SX1278	CS
int sck = 15;
int mosi = 16;
int miso = 14;
int dio0 = 20;
int reset = 21;
 
// Define Modes
#define SX1278_MODE_RX_CONTINUOUS			        0x00
#define SX1278_MODE_TX						0x00
#define SX1278_MODE_SLEEP					0x00
#define SX1278_MODE_STANDBY					0x00
 
// System Definitions for SX1278
// Filename : SX1278.h
 
 
#define 	CRC_4_5
 
// Note - these have been commented out as they are problematic. Will attempt to add them in the future.
/*
#ifdef	CR_4_5
	#define	CR	0x01
#else
	#ifdef	CR_4_6
	  #define	CR	0x02
	#else
	  #ifdef	CR_4_7
	    #define	CR	0x03
	  #else
	    #ifdef	CR_4_8
	      #define	CR	0x04
	    #endif
	  #endif
	#endif
#endif
*/
 
#define   CR    0x01
 
#define      CRC_EN
 
#ifdef      CRC_EN
  #define   CRC    0x01
#else
  #define  CRC    0x00
#endif
 
#define	LR_RegFifo 	0x00
#define	LR_RegOpMode 	0x01
#define	LR_RegFrMsb 	0x06
#define	LR_RegFrMid 	0x07
#define	LR_RegFrLsb 	0x08
#define	LR_RegPaConfig 	0x09
#define	LR_RegPaRamp 	0x0A
#define	LR_RegOcp 	0x0B
#define	LR_RegLna 	0x0C
#define	LR_RegFifoAddrPtr 	0x0D
#define	LR_RegFifoTxBaseAddr	0x0E
#define	LR_RegFifoRxBaseAddr	0x0F
#define	LR_RegFifoRxCurrentAddr	0x10
#define	LR_RegIrqFlagsMask	0x11
#define	LR_RegIrqFlags 	0x12
#define	LR_RegRxNbBytes 	0x13
#define	LR_RegRxHeaderCntValueMsb	0x14
#define	LR_RegRxHeaderCntValueLsb	0x15
#define	LR_RegRxPacketCntValueMsb	0x16
#define	LR_RegRxPacketCntValueLsb	0x17
#define	LR_RegModemStat 	0x18
#define	LR_RegPktSnrValue 	0x19
#define	LR_RegPktRssiValue 	0x1A
#define	LR_RegRssiValue 	0x1B
#define	LR_RegHopChannel 	0x1C
#define	LR_RegModemConfig1	0x1D
#define	LR_RegModemConfig2	0x1E	
#define	LR_RegSymbTimeoutLsb	0x1F
#define	LR_RegPreambleMsb 	0x20
#define	LR_RegPreambleLsb 	0x21
#define	LR_RegPayloadLength 	0x22
#define	LR_RegMaxPayloadLength	0x23
#define	LR_RegHopPeriod 	0x24
#define	LR_RegFifoRxByteAddr	0x25
 
#define	REG_LR_DIOMAPPING1	0x40
#define	REG_LR_DIOMAPPING2	0x41
 
#define	REG_LR_VERSION	0x42
 
#define	REG_LR_PLLHOP	0x44
#define	REG_LR_TCX0	0x4B
#define	REG_LR_PADAC	0x4D
#define	REG_LR_FORMERTEMP	0x5B
 
#define	REG_LR_AGCREF	0x61
#define	REG_LR_AGCTHRESH1	0x62
#define	REG_LR_AGCTHRESH1	0x62
#define	REG_LR_AGCTHRESH3	0x64
 
 
#define	RegFIFO	0x00
#define	RegOpMode	0x01
#define	RegBitRateMsb	0x02
#define	RegBitRateLsb	0x03
#define	RegFdevMsb	0x04
#define	RegFdevLsb	0x05
#define	RegFreqMsb	0x06
#define	ReqFreqMid	0x07
#define	RegFreqLsb	0x08
#define	RegPaConfig	0x09
#define	RegPaRamp	0x0A
#define	RegOcp	0x0B
#define	RegLna	0x0C
#define	RegRxConfig	0x0D
#define	RegRssiConfig	0x0E
#define	RegRssiCollision	0x0F
#define	RegRssiThresh	0x10
#define	RegRssiValue	0x11
#define	RegRxBw	0x12
#define	RegAfcBw	0x13
#define	RegOokPeak	0x14
#define	RegOokFix	0x15
#define	RegOokAvg	0x16
 
#define	RegAfcFei	0x1A
#define	RegAfcMsb	0x1B
#define	RegAfcLsb                               0x1C
#define	RegFeiMsb                               0x1D
#define	RegFeiLsb                               0x1E
#define	RegPreambleDetect                       0x1F
#define	RegRxTimeout1                           0x20
#define	RegRxTimeout2                           0x21
 
#define	RegRxTimeout3                           0x22
 
#define	RegRxDelay                              0x23
#define	RegOsc                                  0x24
 
#define	RegPreambleMsb                          0x25
#define	RegPreambleLsb                          0x26
 
#define	RegSyncConfig                           0x27
#define	RegSyncValue1                           0x28
#define	RegSyncValue2                           0x29
#define	RegSyncValue3                           0x2A
#define	RegSyncValue4                           0x2B
#define	RegSyncValue5                           0x2C
 
#define	RegSyncValue6                           0x2D
#define	RegSyncValue7                           0x2E
#define	RegSyncValue8                           0x2F
#define	RegPacketConfig1                        0x30
#define	RegPacketConfig2                        0x31
 
#define	RegPayloadLength                        0x32
#define	RegNodeAdrs                             0x33
#define	RegBroadcastAdrs                        0x34
#define	RegFifoThresh                           0x35
 
#define	RegSeqConfig1                           0x36
#define	RegSeqConfig2                           0x37
 
#define	RegTimerResol                           0x38
#define	RegTimer1Coef                           0x39
#define	RegTimer2Coef                           0x3A
#define	RegImageCal                             0x3B
 
#define	RegTemp                                 0x3C
#define	RegLowBat                               0x3D
#define	RegIrqFlags1                            0x3E
 
#define	RegIrqFlags2                            0x3F
 
#define	RegDioMapping1                          0x40
#define	RegDioMapping2                          0x41
#define	RegVersion                              0x42
#define	RegPllHop                               0x44
 
#define	RegPaDac                                0x4D
 
 
 
void SPICmd8bit(unsigned char WrPara)
{
	unsigned char bitcnt;
 
	digitalWrite(nsel, LOW);
 
	digitalWrite(sck, LOW);
 
	for (bitcnt=8; bitcnt != 0; bitcnt--)
	{
		digitalWrite(sck, LOW);
 
			if (WrPara&0x80) {
				digitalWrite(mosi, HIGH);
				}
			else {
				digitalWrite(mosi, LOW);
				}
 
		digitalWrite(sck, HIGH);
		WrPara <<= 1;
	}
 
	digitalWrite(sck, LOW);
	digitalWrite(mosi, HIGH);
}	
 
unsigned char SPIRead8bit(void)
{
	unsigned char RdPara = 0;
	unsigned char bitcnt;
 
	digitalWrite(nsel, LOW);
	digitalWrite(mosi, HIGH);
 
	for ( bitcnt=8; bitcnt !=0; bitcnt--) {
		digitalWrite(sck, LOW);
		RdPara <<= 1;
		digitalWrite(sck, HIGH);
 
		if(digitalRead(miso)) {
			RdPara |= 0x01;
			}
		else {
			RdPara |= 0x00;
			}
 
	}
	digitalWrite(sck, LOW);
	return(RdPara);
}
 
 
unsigned char SPIRead(unsigned char adr)
{
	unsigned char tmp;
	SPICmd8bit(adr);
	tmp = SPIRead8bit();
	digitalWrite(nsel, HIGH);
	return(tmp);
}
 
 
void SPIWrite(unsigned char adr, unsigned char WrPara)
{
	digitalWrite(nsel, LOW);
	SPICmd8bit(adr|0x80);
	SPICmd8bit(WrPara);
 
	digitalWrite(sck, LOW);
	digitalWrite(mosi, HIGH);
	digitalWrite(nsel, HIGH);
}
 
 
void SPIBurstRead(unsigned char adr, unsigned char *ptr, unsigned char leng)
{
	unsigned char i;
		if (leng<=1) {
			return;
		}
		else {
			digitalWrite(sck, LOW);
			digitalWrite(nsel, LOW);
			SPICmd8bit(adr);
 
			for (i=0; i<leng; i++ ) {
				ptr[i] = SPIRead8bit();
			}
 
			digitalWrite(nsel, HIGH);
		}
}
 
 
void BurstWrite(unsigned char adr, unsigned char *ptr, unsigned char leng)
{
	unsigned char i;
 
	if (leng <= 1) {
		return;
	}
	else {
	digitalWrite(sck, LOW);
	digitalWrite(nsel, LOW);
	SPICmd8bit(adr|0x80);
 
		for (i=0; i<leng; i++) {
			SPICmd8bit(ptr[i]);
		}
	digitalWrite(nsel, HIGH);
	}
}
 
 
	// Parameter Table Definition
 
unsigned char sx1278FreqTbl[1][3] =
{
	{ 0x6C, 0x80, 0x00}, //434Mhz
};
 
 
unsigned char sx1278PowerTbl[4] =
{
	0xFF,
	0xFC,
	0xF9,
	0xF6,
};
 
 
unsigned char sx1278SpreadFactorTbl[7] =
{
	6,7,8,9,10,11,12
};	
 
 
unsigned char sx1278LoRaBwTbl[10] =
{
	0,1,2,3,4,5,6,7,8,9		// 7.8Khz, 10.4KHz, 15.6KHz, 20.8KHz, 31.2KHz, 41.7KHz, 62.5KHz, 125KHz, 250KHz, 500KHz
};
 
 
unsigned char sx1278Data[] = {"Mark1 Lora sx1278"};
 
unsigned char RxData[64];
 
 
void sx1278_Standby(void)
{
	SPIWrite(LR_RegOpMode, 0x09);	// Standby & Low Frequency mode
	// SPIWrite(LR_RegOpMode, 0x01);	// standby high frfequency mode
}	
 
void sx1278_Sleep(void)	
{	
	SPIWrite(LR_RegOpMode, 0x08); 	// Sleep & Low Frequency mode
	// SPIWrite(LR_RegOpMode, 0x00); 	// Sleep / high frequency mode
 
}	
 
void sx1278_EntryLoRa(void)
{
	SPIWrite(LR_RegOpMode, 0x88); 	// Low frequency mode
	// SPIWrite(LR_RegOpMode, 0x80); 	// Sigh frequency mode
}
 
void sx1278_LoRaClearIrq(void)
{
	SPIWrite(LR_RegIrqFlags, 0xFF);
}
 
 
unsigned char sx1278_LoRaEntryRx(void)
{
	unsigned char addr;
	console.println("Console: Enter sx76 Config");
	sx1278_Config();	// setting base parater
 
	SPIWrite(REG_LR_PADAC, 0x84 );
	SPIWrite(LR_RegHopPeriod, 0xFF);
	SPIWrite(REG_LR_DIOMAPPING1, 0x01 );
 
	SPIWrite(LR_RegIrqFlagsMask, 0x3f);
 
    sx1278_LoRaClearIrq();
 
	SPIWrite(LR_RegPayloadLength, 21);
 
	addr = SPIRead(LR_RegFifoRxBaseAddr);
 
	SPIWrite(LR_RegFifoAddrPtr, addr);
	SPIWrite(LR_RegOpMode, 0x8d);			// Set the Operating Mode to Continuos Rx Mode && Low Frequency Mode
 
    	while (1) 	{
			if ((SPIRead(LR_RegModemStat) & 0x04) == 0x04) {
				break;
            }    
				return 0;    
	}
}	
 
 
unsigned char sx1278_LoRaReadRSSI(void)
{
	unsigned int temp = 10;
	temp = SPIRead(LR_RegRssiValue);
	temp = temp + 127 - 137;
	return (unsigned char) temp;
}
 
 
 
unsigned char sx1278_LoRaRxPacket (void)
{
	unsigned char i;
	unsigned char addr;
	unsigned char packet_size;
 
	if (digitalRead(dio0)) 	{
	       console.println("Console: DIO_0 shows packet recieved");
 
        	for (i = 0; i < 32; i++ ) {
				RxData[i] = 0x00;
			}
 
	addr = SPIRead(LR_RegFifoRxCurrentAddr);
	SPIWrite(LR_RegFifoAddrPtr, addr);		// RXBaseAddr --> FiFoAddrPtr
 
	if (sx1278SpreadFactorTbl[Lora_Rate_Sel] == 6 ) {
		packet_size = 21;
	} else {
		packet_size = SPIRead(LR_RegRxNbBytes);
		}
 
	SPIBurstRead(0x00, RxData, packet_size);
 
	sx1278_LoRaClearIrq();
 
	for ( i = 0; i< 17; i++ ) {
		if (RxData[i] != sx1278Data[i] ) break;
	}
 
	if ( i > 17 ) {
		return (i);
	} else return (0);
 
	}
	else return(0); // if !(digitalRead(dio0) --> this is important for recieving packets
}
 
 
unsigned char sx1278_LoRaEntryTx(void)
{
	unsigned char addr, temp;
 
	sx1278_Config();	// setting base parater
 
	SPIWrite(REG_LR_PADAC, 0x87 );
	SPIWrite(LR_RegHopPeriod, 0x00);
	SPIWrite(REG_LR_DIOMAPPING1, 0x41 );
 
	sx1278_LoRaClearIrq();
	SPIWrite(LR_RegIrqFlagsMask, 0xF7);
	SPIWrite(LR_RegPayloadLength, 21);
 
	addr = SPIRead(LR_RegFifoTxBaseAddr);
 
	SPIWrite(LR_RegFifoAddrPtr, addr);
 
	while (1) {
		temp = SPIRead(LR_RegPayloadLength);
		if (temp==21) break;
	}
 
}
 
unsigned char sx1278_LoRaTxPacket(void)
{
	unsigned char TxFlag = 0;
	unsigned char addr;
 
	BurstWrite(0x00, (unsigned char *)sx1278Data, 21);
	SPIWrite(LR_RegOpMode, 0x8b);
 
	while(1) {
		if (digitalRead(dio0)) 	{
			SPIRead(LR_RegIrqFlags);
			sx1278_LoRaClearIrq();
			sx1278_Standby();
			break;
		}
	}
}
 
unsigned char sx1278_ReadRSSI(void)
{
	unsigned char temp = 0xff;
 
	temp = SPIRead(0x11);
	temp >>= 1;
	temp = 127 - temp;
	return temp;
}
 
 
 
void sx1278_Config(void) {
	unsigned char i;
	sx1278_Sleep();	// modem must be in sleep mode
 
	for ( i = 250; i!= 0; i-- );
 
	delay(15);
 
	//lora mode
	sx1278_EntryLoRa();
 
	// SPIWrite(0x5904); // change digital regulator from 1.6V to 1.47V: see errata note
 
	BurstWrite(LR_RegFrMsb, sx1278FreqTbl[Freq_Sel],3); //set the frequency parameter
 
	// set the base parameters
 
	SPIWrite(LR_RegPaConfig, sx1278PowerTbl[Power_Sel]); // set the output power parameter
 
	SPIWrite(LR_RegOcp, 0x0B); 
	SPIWrite(LR_RegLna, 0x23);
 
	if(sx1278SpreadFactorTbl[Lora_Rate_Sel]==6)
	{	
		unsigned char tmp;
 
		SPIWrite(LR_RegModemConfig1, ((sx1278LoRaBwTbl[BandWide_Sel] << 4) +  (CR<<1 ) + 0x01 ));
		// Implicit Enable CRC Enable (0x02) & Error Coding rate 4/5 (0x01), 4/6 (0x02), 4/7 (0x03), 4/8 (0x04)
 
		SPIWrite(LR_RegModemConfig2, ((sx1278SpreadFactorTbl[Lora_Rate_Sel] << 4 ) + (CRC<<2 ) + 0x03 ));
 
		tmp = SPIRead(0x31);
		tmp &= 0xF8;
		tmp |= 0x05;
		SPIWrite(0x31,tmp);
		SPIWrite(0x37, 0x0C);
	}
 
	else {
		SPIWrite(LR_RegModemConfig1, ((sx1278LoRaBwTbl[BandWide_Sel] << 4)+(CR<<1)+0x00));
		SPIWrite(LR_RegModemConfig2, ((sx1278SpreadFactorTbl[Lora_Rate_Sel]<<4)+(CRC<<2)+0x03));
	}
 
	SPIWrite(LR_RegSymbTimeoutLsb, 0xFF);
	SPIWrite(LR_RegPreambleMsb, 0x00);
	SPIWrite(LR_RegPreambleLsb, 12);
	SPIWrite(REG_LR_DIOMAPPING2, 0x01);
	sx1278_Standby();
}	
 
 
void setup() {
    pinMode(led, OUTPUT);
    pinMode(nsel, OUTPUT);
    pinMode(sck, OUTPUT);
    pinMode(mosi, OUTPUT);
    pinMode(miso, OUTPUT);
    pinMode(reset, OUTPUT);
 
    Serial.begin(9600);
    console.begin(9600);
    console.println("########################################");
    delay(10);	
    console.println("Console: Software Serial Port Connected");
    delay(10);	
    console.println("#########################################");
    for (int i=0; i<200; i++);
    {
      console.print("&");
      delay(10);
    }
    console.println(" ");  
 
}    
 
 
void loop() {
// this is the main code to run repeatedly
	mode 	= 0x01; 	//lora mode
	Freq_Sel 	= 0x00; 	//433Mhz
	Power_Sel 	= 0x00; 	//
	Lora_Rate_Sel 	= 0x06;
	BandWide_Sel 	= 0x07;
	Fsk_Rate_Sel 	= 0x00;
         // added this as the programmer was not workiing....
        console.println("####################");
        delay(10);	
        console.println("LoRa-Cleint");
        delay(10);
        console.println("####################");
        delay(1000);
 
        sx1278_Config();
        sx1278_LoRaEntryRx();
 
 
        console.println("Console: RX Data buffer contains");
        for (int i=0; i<64; i++) {
          console.print(RxData[i]);
        }
        console.println(" ");
 
        digitalWrite(led, HIGH); 	// turn the LED on
	delay(500); 	// wait for 500ms
	digitalWrite(led, LOW); 	// turn the LED off
	delay(500);	// wait for 500ms
 
        int loopCnt = 0;
	while(1) {
 
	// Slave
	console.println("Console: Waiting for RX packet  ");
        char fromSPI = SPIRead(LR_RegFifoRxCurrentAddr);
        console.print("Console: Reg FIFO Rx Current Address  ");
        console.print(fromSPI, HEX);
        console.println(" ");
        console.println(" ");
        delay(1000);
 
        // check the Modem Status Indicators
 
        // frmo thr ModemStatus bits in RegModemStat
        char lrModemStat = SPIRead(LR_RegModemStat);
        // Signal Detected bit 0
        console.println();
        console.print("Console: RegModem (LoRa) Stat 0x");
        console.print(lrModemStat, HEX);
        console.println();
 
       SPIWrite(LR_RegOpMode, 0x15);
       digitalWrite(dio0, HIGH);
       delay(5000);
 
 
       char showOpMode = SPIRead(LR_RegOpMode);
 
       if (showOpMode && 0x80 == 0 )
           console.println("Console: OpMode is FSK");
       else
           console.println("Console: OpMode is LoRa");
 
       showOpMode = SPIRead(LR_RegOpMode);// && 0xF8;
       console.print("Console: OpMode Regsiters = ");
       console.print(showOpMode, HEX);
       console.println(" ");
 
 
       char RSSIVal = SPIRead(0x1B);
       console.print("Console: RSSI is ");
       console.print(RSSIVal, HEX);
       console.print(" dBm");
       console.println(" ");
 
 
	if(sx1278_LoRaRxPacket())  // this does not seem to be used
	{
 
  	digitalWrite(led, HIGH);
	delay(500);
	digitalWrite(led, LOW);
	delay(500);
	}	
 
        // console.println("End of loop");
        console.println("Console: RX Data buffer contains ");
            for (int i=0; i<64; i++) {
              console.print(char(RxData[i]));
              console.print(" ");
              }
 
         for (int i=0; i<200; i++) {
              console.print(".");
              delay(10);
            }
        console.println(" ");    
 
        sx1278_LoRaEntryRx();
 
 
}
}

Code: LoRa Server

lora_server.ino
/*************************************
Project: Pro Micro Arduino + LoRa iMod 4 Server
Data Rate : Determined by program
Frequency: 433Mhz
Modulation: LoRA
Transmit mode : continuous receive
*************************************/
 
#include <SoftwareSerial.h>
 
/*************************************
Software Serial Setup
Data Rate : 9600bps
Pinouts: RX (yellow wire) -> TXO (pin 0), TX (red wire) -> RX0, GNd (Blue) -> GND
Transmit mode : continuous transmit
*************************************/
 
SoftwareSerial console(1, 0);    // RX, TX
 
 
unsigned char mode; //lora --1 / FSK --0
unsigned char Freq_Sel; //
unsigned char Power_Sel; //
unsigned char Lora_Rate_Sel; //
unsigned char BandWide_Sel; //
unsigned char Fsk_Rate_Sel; //
 
 
/*
Pro Micro Pintouts
 
SCK 	15          
MOSI	16         
MISO	14
RESET 	A3, 21
DIO0 / D5	A2, 20
NSEL / CS       A0, 18
LED / D14 	A1, 19	
 
 
 
*/
 
// Pinout for Arduino Pro Micro
// 
//
//
//
 
int led = 19; 					// Pro Micro P19, A1, D14
int nsel = 18;					// Pro Micro P18, A0, 	SX1278	CS
int sck = 15;
int mosi = 16;
int miso = 14;
int dio0 = 20;
int reset = 21;
 
// Define Modes
#define SX1278_MODE_RX_CONTINUOUS			        0x00
#define SX1278_MODE_TX						0x00
#define SX1278_MODE_SLEEP					0x00
#define SX1278_MODE_STANDBY					0x00
 
// System Definitions for SX1278
// Filename : SX1278.h
 
 
#define 	CRC_4_5
/*
#ifdef	CR_4_5
	#define	CR	0x01
#else
	#ifdef	CR_4_6
	  #define	CR	0x02
	#else
	  #ifdef	CR_4_7
	    #define	CR	0x03
	  #else
	    #ifdef	CR_4_8
	      #define	CR	0x04
	    #endif
	  #endif
	#endif
#endif
*/
 
#define   CR    0x01
 
#define      CRC_EN
 
#ifdef      CRC_EN
  #define   CRC    0x01
#else
  #define  CRC    0x00
#endif
 
#define	LR_RegFifo 	0x00
#define	LR_RegOpMode 	0x01
#define	LR_RegFrMsb 	0x06
#define	LR_RegFrMid 	0x07
#define	LR_RegFrLsb 	0x08
#define	LR_RegPaConfig 	0x09
#define	LR_RegPaRamp 	0x0A
#define	LR_RegOcp 	0x0B
#define	LR_RegLna 	0x0C
#define	LR_RegFifoAddrPtr 	0x0D
#define	LR_RegFifoTxBaseAddr	0x0E
#define	LR_RegFifoRxBaseAddr	0x0F
#define	LR_RegFifoRxCurrentAddr	0x10
#define	LR_RegIrqFlagsMask	0x11
#define	LR_RegIrqFlags 	0x12
#define	LR_RegRxNbBytes 	0x13
#define	LR_RegRxHeaderCntValueMsb	0x14
#define	LR_RegRxHeaderCntValueLsb	0x15
#define	LR_RegRxPacketCntValueMsb	0x16
#define	LR_RegRxPacketCntValueLsb	0x17
#define	LR_RegModemStat 	0x18
#define	LR_RegPktSnrValue 	0x19
#define	LR_RegPktRssiValue 	0x1A
#define	LR_RegRssiValue 	0x1B
#define	LR_RegHopChannel 	0x1C
#define	LR_RegModemConfig1	0x1D
#define	LR_RegModemConfig2	0x1E	
#define	LR_RegSymbTimeoutLsb	0x1F
#define	LR_RegPreambleMsb 	0x20
#define	LR_RegPreambleLsb 	0x21
#define	LR_RegPayloadLength 	0x22
#define	LR_RegMaxPayloadLength	0x23
#define	LR_RegHopPeriod 	0x24
#define	LR_RegFifoRxByteAddr	0x25
 
#define	REG_LR_DIOMAPPING1	0x40
#define	REG_LR_DIOMAPPING2	0x41
 
#define	REG_LR_VERSION	0x42
 
#define	REG_LR_PLLHOP	0x44
#define	REG_LR_TCX0	0x4B
#define	REG_LR_PADAC	0x4D
#define	REG_LR_FORMERTEMP	0x5B
 
#define	REG_LR_AGCREF	0x61
#define	REG_LR_AGCTHRESH1	0x62
#define	REG_LR_AGCTHRESH1	0x62
#define	REG_LR_AGCTHRESH3	0x64
 
 
#define	RegFIFO	0x00
#define	RegOpMode	0x01
#define	RegBitRateMsb	0x02
#define	RegBitRateLsb	0x03
#define	RegFdevMsb	0x04
#define	RegFdevLsb	0x05
#define	RegFreqMsb	0x06
#define	ReqFreqMid	0x07
#define	RegFreqLsb	0x08
#define	RegPaConfig	0x09
#define	RegPaRamp	0x0A
#define	RegOcp	0x0B
#define	RegLna	0x0C
#define	RegRxConfig	0x0D
#define	RegRssiConfig	0x0E
#define	RegRssiCollision	0x0F
#define	RegRssiThresh	0x10
#define	RegRssiValue	0x11
#define	RegRxBw	0x12
#define	RegAfcBw	0x13
#define	RegOokPeak	0x14
#define	RegOokFix	0x15
#define	RegOokAvg	0x16
 
#define	RegAfcFei	0x1A
#define	RegAfcMsb	0x1B
#define	RegAfcLsb                               0x1C
#define	RegFeiMsb                               0x1D
#define	RegFeiLsb                               0x1E
#define	RegPreambleDetect                       0x1F
#define	RegRxTimeout1                           0x20
#define	RegRxTimeout2                           0x21
 
#define	RegRxTimeout3                           0x22
 
#define	RegRxDelay                              0x23
#define	RegOsc                                  0x24
 
#define	RegPreambleMsb                          0x25
#define	RegPreambleLsb                          0x26
 
#define	RegSyncConfig                           0x27
#define	RegSyncValue1                           0x28
#define	RegSyncValue2                           0x29
#define	RegSyncValue3                           0x2A
#define	RegSyncValue4                           0x2B
#define	RegSyncValue5                           0x2C
 
#define	RegSyncValue6                           0x2D
#define	RegSyncValue7                           0x2E
#define	RegSyncValue8                           0x2F
#define	RegPacketConfig1                        0x30
#define	RegPacketConfig2                        0x31
 
#define	RegPayloadLength                        0x32
#define	RegNodeAdrs                             0x33
#define	RegBroadcastAdrs                        0x34
#define	RegFifoThresh                           0x35
 
#define	RegSeqConfig1                           0x36
#define	RegSeqConfig2                           0x37
 
#define	RegTimerResol                           0x38
#define	RegTimer1Coef                           0x39
#define	RegTimer2Coef                           0x3A
#define	RegImageCal                             0x3B
 
#define	RegTemp                                 0x3C
#define	RegLowBat                               0x3D
#define	RegIrqFlags1                            0x3E
 
#define	RegIrqFlags2                            0x3F
 
#define	RegDioMapping1                          0x40
#define	RegDioMapping2                          0x41
#define	RegVersion                              0x42
#define	RegPllHop                               0x44
 
#define	RegPaDac                                0x4D
 
 
 
void SPICmd8bit(unsigned char WrPara)
{
	unsigned char bitcnt;
 
	digitalWrite(nsel, LOW);
 
	digitalWrite(sck, LOW);
 
	for (bitcnt=8; bitcnt != 0; bitcnt--)
	{
		digitalWrite(sck, LOW);
 
			if (WrPara&0x80) {
				digitalWrite(mosi, HIGH);
				}
			else {
				digitalWrite(mosi, LOW);
				}
 
		digitalWrite(sck, HIGH);
		WrPara <<= 1;
	}
 
	digitalWrite(sck, LOW);
	digitalWrite(mosi, HIGH);
}	
 
unsigned char SPIRead8bit(void)
{
	unsigned char RdPara = 0;
	unsigned char bitcnt;
 
	digitalWrite(nsel, LOW);
	digitalWrite(mosi, HIGH);
 
	for ( bitcnt=8; bitcnt !=0; bitcnt--) {
		digitalWrite(sck, LOW);
		RdPara <<= 1;
		digitalWrite(sck, HIGH);
 
		if(digitalRead(miso)) {
			RdPara |= 0x01;
			}
		else {
			RdPara |= 0x00;
			}
 
	}
	digitalWrite(sck, LOW);
	return(RdPara);
}
 
 
unsigned char SPIRead(unsigned char adr)
{
	unsigned char tmp;
	SPICmd8bit(adr);
	tmp = SPIRead8bit();
	digitalWrite(nsel, HIGH);
	return(tmp);
}
 
 
void SPIWrite(unsigned char adr, unsigned char WrPara)
{
	digitalWrite(nsel, LOW);
	SPICmd8bit(adr|0x80);
	SPICmd8bit(WrPara);
 
	digitalWrite(sck, LOW);
	digitalWrite(mosi, HIGH);
	digitalWrite(nsel, HIGH);
}
 
 
void SPIBurstRead(unsigned char adr, unsigned char *ptr, unsigned char leng)
{
	unsigned char i;
		if (leng<=1) {
			return;
		}
		else {
			digitalWrite(sck, LOW);
			digitalWrite(nsel, LOW);
			SPICmd8bit(adr);
 
			for (i=0; i<leng; i++ ) {
				ptr[i] = SPIRead8bit();
			}
 
			digitalWrite(nsel, HIGH);
		}
}
 
 
void BurstWrite(unsigned char adr, unsigned char *ptr, unsigned char leng)
{
	unsigned char i;
 
	if (leng <= 1) {
		return;
	}
	else {
	digitalWrite(sck, LOW);
	digitalWrite(nsel, LOW);
	SPICmd8bit(adr|0x80);
 
		for (i=0; i<leng; i++) {
			SPICmd8bit(ptr[i]);
		}
	digitalWrite(nsel, HIGH);
	}
}
 
 
	// Parameter Table Definition
 
unsigned char sx1278FreqTbl[1][3] =
{
	{ 0x6C, 0x80, 0x00}, //434Mhz
};
 
 
unsigned char sx1278PowerTbl[4] =
{
	0xFF,
	0xFC,
	0xF9,
	0xF6,
};
 
 
unsigned char sx1278SpreadFactorTbl[7] =
{
	6,7,8,9,10,11,12
};	
 
 
unsigned char sx1278LoRaBwTbl[10] =
{
	0,1,2,3,4,5,6,7,8,9		// 7.8Khz, 10.4KHz, 15.6KHz, 20.8KHz, 31.2KHz, 41.7KHz, 62.5KHz, 125KHz, 250KHz, 500KHz
};
 
 
unsigned char sx1278Data[] = {"SX1278 Test Module"};
 
unsigned char RxData[64];
 
 
void sx1278_Standby(void)
{
	SPIWrite(LR_RegOpMode, 0x09);	// Standby & Low Frequency mode
	// SPIWrite(LR_RegOpMode, 0x01);	// standby high frfequency mode
}	
 
void sx1278_Sleep(void)	
{	
	SPIWrite(LR_RegOpMode, 0x08); 	// Sleep & Low Frequency mode
	// SPIWrite(LR_RegOpMode, 0x00); 	// Sleep / high frequency mode
 
}	
 
void sx1278_EntryLoRa(void)
{
	SPIWrite(LR_RegOpMode, 0x88); 	// Low frequency mode
	// SPIWrite(LR_RegOpMode, 0x80); 	// Sigh frequency mode
}
 
void sx1278_LoRaClearIrq(void)
{
	SPIWrite(LR_RegIrqFlags, 0xFF);
}
 
 
unsigned char sx1278_LoRaEntryRx(void)
{
	unsigned char addr;
	console.println("Enter sx76 Config");
	sx1278_Config();	// setting base parater
 
	SPIWrite(REG_LR_PADAC, 0x84 );
	SPIWrite(LR_RegHopPeriod, 0xFF);
	SPIWrite(REG_LR_DIOMAPPING1, 0x01 );
 
	SPIWrite(LR_RegIrqFlagsMask, 0x3f);
 
	sx1278_LoRaClearIrq();
 
	SPIWrite(LR_RegPayloadLength, 21);
 
	addr = SPIRead(LR_RegFifoRxBaseAddr);
 
	SPIWrite(LR_RegFifoAddrPtr, addr);
	SPIWrite(LR_RegOpMode, 0x8d);			// Set the Operating Mode to Continuos Rx Mode && Low Frequency Mode
 
    while (1) 	{
			if ((SPIRead(LR_RegModemStat) & 0x04) == 0x04) {
				break;
            }    
				return 0;    
	}
}	
 
 
unsigned char sx1278_LoRaReadRSSI(void)
{
	unsigned int temp = 10;
	temp = SPIRead(LR_RegRssiValue);
	temp = temp + 127 - 137;
	return (unsigned char) temp;
}
 
 
 
unsigned char sx1278_LoRaRxPacket (void)
{
	unsigned char i;
	unsigned char addr;
	unsigned char packet_size;
 
 
	if (digitalRead(dio0)) 	{
	       console.println("DIO_0 shows packet recieved");
 
        	for (i = 0; i < 32; i++ ) {
				RxData[i] = 0x00;
			}
 
	addr = SPIRead(LR_RegFifoRxCurrentAddr);
	SPIWrite(LR_RegFifoAddrPtr, addr);		// RXBaseAddr --> FiFoAddrPtr
 
	if (sx1278SpreadFactorTbl[Lora_Rate_Sel] == 6 ) {
		packet_size = 21;
	} else {
		packet_size = SPIRead(LR_RegRxNbBytes);
		}
 
	SPIBurstRead(0x00, RxData, packet_size);
 
	sx1278_LoRaClearIrq();
 
	for ( i = 0; i< 17; i++ ) {
		if (RxData[i] != sx1278Data[i] ) break;
	}
 
	if ( i > 17 ) {
		return (i);
	} else return (0);
 
	}
	else return(0); // if !(digitalRead(dio0) --> this is important for recieving packets
}
 
 
unsigned char sx1278_LoRaEntryTx(void)
{
	unsigned char addr, temp;
 
	sx1278_Config();	// setting base parater
 
	SPIWrite(REG_LR_PADAC, 0x87 );
	SPIWrite(LR_RegHopPeriod, 0x00);
	SPIWrite(REG_LR_DIOMAPPING1, 0x41 );
 
	sx1278_LoRaClearIrq();
	SPIWrite(LR_RegIrqFlagsMask, 0xF7);
	SPIWrite(LR_RegPayloadLength, 21);
 
	addr = SPIRead(LR_RegFifoTxBaseAddr);
 
	SPIWrite(LR_RegFifoAddrPtr, addr);
 
	while (1) {
		temp = SPIRead(LR_RegPayloadLength);
		if (temp==21) break;
	}
 
}
 
unsigned char sx1278_LoRaTxPacket(void)
{
	unsigned char TxFlag = 0;
	unsigned char addr;
 
	BurstWrite(0x00, (unsigned char *)sx1278Data, 21);
	SPIWrite(LR_RegOpMode, 0x8b);
 
	while(1) {
		if (digitalRead(dio0)) 	{
			SPIRead(LR_RegIrqFlags);
			sx1278_LoRaClearIrq();
			sx1278_Standby();
			break;
		}
	}
}
 
unsigned char sx1278_ReadRSSI(void)
{
	unsigned char temp = 0xff;
 
	temp = SPIRead(0x11);
	temp >>= 1;
	temp = 127 - temp;
	return temp;
}
 
 
 
 
 
void sx1278_Config(void) {
	unsigned char i;
	sx1278_Sleep();		// modem must be in sleep mode
 
//	for ( i = 250; i!= 0; i-- );
	for ( i = 250; i!= 0; i-- )
        {
	delay(15);
	}
 
	//lora mode
	sx1278_EntryLoRa();
 
	//SPIWrite(0x5904); // change digital regulator from 1.6V to 1.47V: see errata note
 
	BurstWrite(LR_RegFrMsb, sx1278FreqTbl[Freq_Sel],3); //set the frequency parameter
 
	// set the base parameters
 
	SPIWrite(LR_RegPaConfig, sx1278PowerTbl[Power_Sel]); // set the output power parameter
 
	SPIWrite(LR_RegOcp, 0x0B); 
	SPIWrite(LR_RegLna, 0x23);
 
	if(sx1278SpreadFactorTbl[Lora_Rate_Sel]==6)
	{	
		unsigned char tmp;
 
		SPIWrite(LR_RegModemConfig1, ((sx1278LoRaBwTbl[BandWide_Sel] << 4)+(CR<<1)+0x01));
		// Implicit Enable CRC Enable (0x02) & Error Coding rate 4/5 (0x01), 4/6 (0x02), 4/7 (0x03), 4/8 (0x04)
 
		SPIWrite(LR_RegModemConfig2, ((sx1278SpreadFactorTbl[Lora_Rate_Sel]<<4)+(CRC<<2)+0x03));
 
		tmp = SPIRead(0x31);
		tmp &= 0xF8;
		tmp |= 0x05;
		SPIWrite(0x31,tmp);
		SPIWrite(0x37, 0x0C);
	}
 
	else
	{
          	console.println("config - elseif loop");
  		SPIWrite(LR_RegModemConfig1,((sx1278LoRaBwTbl[BandWide_Sel] <<4 )+(CR<<1)+0x00));
		SPIWrite(LR_RegModemConfig2, ((sx1278SpreadFactorTbl[Lora_Rate_Sel]<<4)+ (CRC<<2)+0x03));
	}
 
	SPIWrite(LR_RegSymbTimeoutLsb, 0xFF);
 
	SPIWrite(LR_RegPreambleMsb, 0x00);
 
	SPIWrite(LR_RegPreambleLsb, 12);
 
	SPIWrite(REG_LR_DIOMAPPING2, 0x01);
 
	sx1278_Standby();
        console.print("Config - finished method, forced Opmde to Standby, opmode is now : ");
        console.print(SPIRead(LR_RegOpMode));
 
 
}	
 
 
void setup() {
    pinMode(led, OUTPUT);
    pinMode(nsel, OUTPUT);
    pinMode(sck, OUTPUT);
    pinMode(mosi, OUTPUT);
    pinMode(miso, OUTPUT);
    pinMode(reset, OUTPUT);
 
    Serial.begin(9600);
    console.begin(9600);
    console.println("Software Serial Port Connected");
    console.print("OPmode is ");
    console.print(SPIRead(LR_RegOpMode), HEX);
    console.print("\n");
 
}    
 
 
void loop() {
// this is the main code to run repeatedly
	mode 			= 0x01; 	//lora mode
	Freq_Sel 		= 0x00; 	//433Mhz
	Power_Sel 		= 0x00; 	//
	Lora_Rate_Sel 	= 0x06;
	BandWide_Sel 	= 0x07;
	Fsk_Rate_Sel 	= 0x00;
 
 
    sx1278_Config();
 
 
	sx1278_LoRaEntryRx();
 
	digitalWrite(led, HIGH); 	// turn the LED on
	delay(500); 				// wait for 500ms
	digitalWrite(led, LOW); 	// turn the LED off
	delay(500);					// wait for 500ms
 
    int loopCnt = 0;
	while(1)
	{
	// Master
	       	char opMode = SPIRead(LR_RegOpMode);
                 console.println(" ");
                 console.print("OpMode Reg Value ");
                 console.print(opMode, HEX);
 
                 switch(opMode){
                   case  0:
                      console.println("OPMode is SLEEP");
                      break;
                   case 1:
                      console.println("OPMode is STANDBY");
                      break;
                 }
 
 
                 console.println(" ");
 
                 if (opMode == 0){
                     SPIWrite(LR_RegOpMode, B00010001);
                     console.println("Forcing OPMode to STANDBY");
                     delay(1000);                
                     console.print("OPMOde is now : ");
                     console.print(SPIRead(LR_RegOpMode), HEX);
                     delay(3000);
                 }
 
                digitalWrite(led, HIGH);
                delay(200);
                console.print(loopCnt);
                console.print(": Check Lora Entry Tx \n");
		sx1278_LoRaEntryTx();
                console.print(loopCnt);
                console.print(": Check Lora TX packet \n");
		sx1278_LoRaTxPacket();
		digitalWrite(led, LOW);
		sx1278_LoRaEntryRx();
		delay(200);
		loopCnt++;
 
                for (int i=0;i<26;i++){
                  sx1278Data[i] = char(0x61 + i);
                }
 
}
}
projects/arduino-lora-server-client1.txt · Last modified: 2017/01/26 21:00 by modtronix