@todor.velev @n.manchevmobb here is some code I was using when I was testing with lora/gps.
#include <SoftwareSerial.h>
#include <Wire.h> // for IIC communication
#include "TimerOne.h"
#include <Adafruit_GPS.h>
//GPS info
Adafruit_GPS GPS(&Serial1);
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences.
#define GPSECHO false
// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy
//************** Device parameters for registration *****************
////////////////////////////////////////////////////////////
char DEVICE_EUI[] = "";
char DEVICE_ADDR[] = ""; //4 bytes required
char APP_KEY[] = ""; //16 bytes required
char NWK_SESSION_KEY[] = ""; //network session key
char APP_SESSION_KEY[] = ""; //network session key
////////////////////////////////////////////////////////////
//************** ACCELEROMETER THRESHOLDS*******************************
#define xThreshold 0.5
#define yThreshold 0.5
#define zThreshold 0.5
//**************** TEMPERATURE SAMPLE TIME *******************************
#define TEMP_SAMPLE_TIME 100 //sample time for temperature
//******************** Channel Status *******************
//set bit channel on = 1, channel off = 0
//bank 0 = channels 0-7, bank 1 = channels 8-15, bank 2 = channels 16-23, bank 3 = channels 24-31, bank 4 = channels 32-39,
//bank 5 = channels 40-47, bank 6 = channels 48-55, bank 7 = channels 56-63, bank 8 = channels 64-71,
//MSB = highest channel number in bank. Example Bank 2 = b11000000. Channels 23 and 22 are on
byte channelBank[] = {B11111111, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B11111111};
#define accAddress 0x1D //right justified accelerometer address
#define tmpAddress 0x48 //right justified TMP112 address
#define I2C_WRITE Wire.write
#define I2C_READ Wire.read
/******************** ACCELEROMETER Data ************/
// adresss of accelerometer
#define adress_acc 0X1D // MMA8653FC and MMA8652FC
// adress of registers for MMA8653FC
#define ctrl_reg1 0x2A
#define ctrl_reg2 0x2B
#define ctrl_reg3 0x2C
#define ctrl_reg4 0x2D
#define ctrl_reg5 0x2E
#define int_source 0x0C
#define status_ 0x00
#define f_setup 0x09
#define out_x_msb 0x01
#define out_y_msb 0x03
#define out_z_msb 0x05
#define sysmod 0x0B
#define xyz_data_cfg 0x0E
#define ff_mt_cfg 0x15
#define ff_mt_src 0x16
#define ff_mt_ths 0x17
#define ff_mt_count 0x18
//************** set resolution of accelerometer *************************
//#define resolution 0.0038; //resolution for 2g
//#define resolution 0.0078; //resolution for 4g
#define resolution 0.0156; //resolution for 8g
//************** set range of accelerometer *************************
//#define range 0x00 //2G full scale
//#define range 0x01 //4G full scale
#define range 0x02 //8G full scale
//************** configure accelerometer *************************
//#define accConfig 0x00 // Output data rate at 800Hz, no auto wake, no auto scale adjust, no fast read mode
//#define accConfig 0x21 // Output data rate at 200Hz, no auto wake, no auto scale adjust, no fast read mode
#define accConfig 0x41 // Output data rate at 50Hz, no auto wake, no auto scale adjust, no fast read mode
//#define accConfig 0x71 // Output data rate at 1.5Hz, no auto wake, no auto scale adjust, no fast read mode
//****************** sensor variables **************************
float axeXnow ;
float axeYnow ;
float axeZnow ;
float axeXprev;
float axeYprev;
float axeZprev;
float tempC;
int printTemp;
int printXaxis;
int printYaxis;
int printZaxis;
long printLat;
long printLong;
long printAlt;
char charVal[4][5];
char charGPS[2][7];
long tempCounter;
//*******************************************************************************************************
SoftwareSerial loraSerial(10, 11); // RX, TX ** Set to 10, 11 for Mega2560 boards
void setup() {
delay(1000); //startup delay - gives Lora module time to reset if cold start
Serial.begin(115200); //terminal serial port
loraSerial.begin(57600);
Wire.begin(); // join i2c bus
ACC_INIT(); //initialize accelerometer
getConfig(); //get module information
setChannelStatus(); //configure channels to be on or off
configureABP(); //configure Access By Personalization (ABP)
//configureOTAA(); //configure Over The Air Activation (OTAA)
Timer1.initialize(500000); // initialize timer1, and set to 0.5 second period
Timer1.attachInterrupt(systemTimer); //set ISR
I2C_READ_ACC(0x01); //get initial readings
axeXprev = axeXnow;
axeYprev = axeYnow;
axeZprev = axeZnow;
tempCounter = 0;
//GPS Setup
// 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
GPS.begin(9600);
// uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// Set the update rate
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
// Request updates on antenna status, comment out to keep quiet
GPS.sendCommand(PGCMD_ANTENNA);
// the nice thing about this code is you can have a timer0 interrupt go off
// every 1 millisecond, and read data from the GPS for you. that makes the
// loop code a heck of a lot easier!
useInterrupt(true);
delay(1000);
}
//GPS Functions
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
// if you want to debug, this is a good time to do it!
#ifdef UDR0
if (GPSECHO)
if (c) UDR0 = c;
// writing direct to UDR0 is much much faster than Serial.print
// but only one character can be written at a time.
#endif
}
void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
String padGPS(String hex){
String validHEX;
int len = hex.length();
switch (len){
case 1:
validHEX = "00000" + hex;
break;
case 2:
validHEX = "0000" + hex;
break;
case 3:
validHEX = "000" + hex;
break;
case 4:
validHEX = "00" + hex;
break;
case 5:
validHEX = "0" + hex;
break;
case 6:
validHEX = hex;
break;
default:
validHEX = hex.substring(len - 6, len);
break;
}
return validHEX;
}
uint32_t timer = millis();
void loop() {
// if a sentence is received, we can check the checksum, parse it...
if (GPS.newNMEAreceived()) {
// a tricky thing here is if we print the NMEA sentence, or data
// we end up not listening and catching other sentences!
// so be very wary if using OUTPUT_ALLDATA and trytng to print out data
//Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // we can fail to parse a sentence in which case we should just wait for another
}
/*if (millis() - timer > 2000) {
timer = millis(); // reset the timer
if (GPS.fix) {
int len;
Serial.print("Lat : ");Serial.println(GPS.latitudeDegrees,4);
printLat = (GPS.latitudeDegrees * 10000);
Serial.print("Lat * 10000: ");Serial.println(printLat);
String stringLat = String(printLat,HEX);
Serial.print("stringLat: ");Serial.println(stringLat);
String hexLat = padGPS(stringLat);
Serial.print("Lat HEX: ");Serial.println(hexLat);
hexLat.toCharArray(charGPS[0],7);
Serial.print("Lat toCharArray: ");Serial.println(hexLat);
Serial.print("Long : ");Serial.println(GPS.longitudeDegrees,4);
printLong = (GPS.longitudeDegrees * 10000);
Serial.print("Long * 10000: ");Serial.println(printLong);
String stringLong = String(printLong,HEX);
Serial.print("stringLong: ");Serial.println(stringLong);
String hexLong = padGPS(stringLong);
Serial.print("Long HEX: ");Serial.println(hexLong);
hexLong.toCharArray(charGPS[1],7);
Serial.print("Long toCharArray: ");Serial.println(hexLong);
Serial.print("Alt: ");Serial.println(GPS.altitude);
printAlt = GPS.altitude;
String stringAlt = String(printAlt,HEX);
Serial.print("stringAlt: ");Serial.println(stringAlt);
String hexAlt = padGPS(stringAlt);
Serial.print("Alt HEX: ");Serial.println(hexAlt);
hexAlt.toCharArray(charGPS[2],7);
Serial.print("Alt toCharArray: ");Serial.println(hexAlt);
Serial.print("Prefix; ");
Serial.println("0188");
Serial.print("Lat; ");
Serial.println(charGPS[0]);
Serial.print("Long; ");
Serial.println(charGPS[1]);
Serial.print("Alt; ");
Serial.println(charGPS[2]);
Serial.print("0188");Serial.print(charGPS[0]);Serial.print(charGPS[1]);Serial.print(charGPS[2]);
}
}*/
while (loraSerial.available()) {
Serial.write(loraSerial.read());
}
if (tempCounter >= TEMP_SAMPLE_TIME) //send data every x time
{
getTemperature();
I2C_READ_ACC(0x01);
sendAllData();
tempCounter = 0;
}
delay(50);
I2C_READ_ACC(0x01);
#if 0
if ((abs(axeXprev-axeXnow))>xThreshold || (abs(axeYprev-axeYnow))>yThreshold || (abs(axeZprev-axeZnow))>zThreshold) //send data if any axis exceeds threshold
{
getTemperature();
sendAllData();
axeXprev = axeXnow;
axeYprev = axeYnow;
axeZprev = axeZnow;
}
#endif
}
void sendAllData(void)
{
Serial.println();
Serial.println("****************************************");
Serial.print("Temperature (deg C): ");Serial.println(tempC);
Serial.print("X Axis Now: ");Serial.println(axeXnow);
Serial.print("Y Axis Now: ");Serial.println(axeYnow);
Serial.print("Z Axis Now: ");Serial.println(axeZnow);
Serial.print("X Axis Previous: ");Serial.println(axeXprev);
Serial.print("Y Axis Previous: ");Serial.println(axeYprev);
Serial.print("Z Axis Previous: ");Serial.println(axeZprev);
if (GPS.fix) {
Serial.print("Location (in degrees, works with Google Maps): ");
Serial.print(GPS.latitudeDegrees, 4);
Serial.print(", ");
Serial.println(GPS.longitudeDegrees, 4);
Serial.print("Alt: ");Serial.println(GPS.altitude);
}
Serial.println();
formatData();
loraSerial.print("mac tx uncnf 10 ");loraSerial.print("0167");loraSerial.print(charVal[0]);
loraSerial.print("0271");loraSerial.print(charVal[1]);loraSerial.print(charVal[2]);loraSerial.println(charVal[3]);
delay(5000);
loraSerial.print("mac tx uncnf 10 ");loraSerial.print("0388");loraSerial.print(charGPS[0]);loraSerial.print(charGPS[1]);loraSerial.println(charGPS[2]);
Serial.print("mac tx uncnf 10 ");Serial.print("0167");Serial.print(charVal[0]);
Serial.print("0471");Serial.print(charVal[1]);Serial.print(charVal[2]);Serial.println(charVal[3]);
Serial.print("mac tx uncnf 10 ");Serial.print("0388");Serial.print(charGPS[0]);Serial.print(charGPS[1]);Serial.println(charGPS[2]);
waitCommandResponse();
}
void systemTimer(void)
{
tempCounter++;
}
//************************ format data for lora tx **********************************
//modified for Cayenne Lora
void formatData(void)
{
int len;
printTemp = int(tempC*10);
String stringT = String(printTemp,HEX);
len = stringT.length();
stringT.toCharArray(charVal[0],5);
leadingZero(0,len);
printXaxis = int(axeXnow * 1000);
String stringX = String(printXaxis,HEX);
len = stringX.length();
stringX.toCharArray(charVal[1],5);
leadingZero(1,len);
printYaxis = int(axeYnow * 1000);
String stringY = String(printYaxis,HEX);
len = stringY.length();
stringY.toCharArray(charVal[2],5);
leadingZero(2,len);
printZaxis = int(axeZnow * 1000);
String stringZ = String(printZaxis,HEX);
len = stringZ.length();
stringZ.toCharArray(charVal[3],5);
leadingZero(3,len);
printLat = (GPS.latitudeDegrees * 10000);
String stringLat = String(printLat,HEX);
String hexLat = padGPS(stringLat);
hexLat.toCharArray(charGPS[0],7);
printLong = (GPS.longitudeDegrees * 10000);
String stringLong = String(printLong,HEX);
String hexLong = padGPS(stringLong);
hexLong.toCharArray(charGPS[1],7);
printAlt = GPS.altitude;
String stringAlt = String(printAlt,HEX);
String hexAlt = padGPS(stringAlt);
hexAlt.toCharArray(charGPS[2],7);
}
//********************* Add leading zeros to hex value ********************************
void leadingZero(byte dataID, byte lenStr)
{
charVal[dataID][4]='\0';
if (lenStr==3)
{
charVal[dataID][3]=charVal[dataID][2];
charVal[dataID][2]=charVal[dataID][1];
charVal[dataID][1]=charVal[dataID][0];
charVal[dataID][0]='0';
}
else if (lenStr==2)
{
charVal[dataID][3]=charVal[dataID][1];
charVal[dataID][2]=charVal[dataID][0];
charVal[dataID][1]='0';
charVal[dataID][0]='0';
}
else if (lenStr==1)
{
charVal[dataID][3]=charVal[dataID][0];
charVal[dataID][2]='0';
charVal[dataID][1]='0';
charVal[dataID][0]='0';
}
}
//****************** Write to I2C Slave Registers *********************************************
void I2C_SEND(unsigned char REG_ADDRESS, unsigned char DATA) //SEND data to MMA7660
{
Wire.beginTransmission(adress_acc);
Wire.write(REG_ADDRESS);
Wire.write(DATA);
Wire.endTransmission();
}
//****************************** Read I2C Slave register *******************************************
void I2C_READ_REG(int ctrlreg_address) //READ number data from i2c slave ctrl-reg register and return the result in a vector
{
unsigned char REG_ADDRESS;
int i=0;
Wire.beginTransmission(adress_acc); //=ST + (Device Adress+W(0)) + wait for ACK
Wire.write(ctrlreg_address); // register to read
Wire.endTransmission();
Wire.requestFrom(adress_acc,1); // read a number of byte and store them in write received
}
//****************** Accelerometer Initialization ************************************
void ACC_INIT()
{
I2C_SEND(ctrl_reg1 ,0X00); // standby to be able to configure
delay(10);
I2C_SEND(f_setup ,B01100000); // set FIFO mode - circular mode 32 byte watermark
delay(5);
I2C_SEND(xyz_data_cfg ,range); // set full range
delay(1);
I2C_SEND(ctrl_reg1 ,accConfig); // configure accelerometer
delay(1);
}
//************************** Read Acceleromter Registers ************************************
void I2C_READ_ACC(int ctrlreg_address) //READ number data from i2c slave ctrl-reg register and return the result in a vector
{
byte REG_ADDRESS[7];
int accel[4];
int i=0;
Wire.beginTransmission(adress_acc); //=ST + (Device Adress+W(0)) + wait for ACK
Wire.write(ctrlreg_address); // store the register to read in the buffer of the wire library
Wire.endTransmission(); // actually send the data on the bus -note: returns 0 if transmission OK-
Wire.requestFrom(adress_acc,7); // read a number of byte and store them in wire.read (note: by nature, this is called an "auto-increment register adress")
for(i=0; i<7; i++) // 7 because on datasheet p.19 if FREAD=0, on auto-increment, the adress is shifted
// according to the datasheet, because it's shifted, outZlsb are in adress 0x00
// so we start reading from 0x00, forget the 0x01 which is now "status" and make the adapation by ourselves
//this gives:
//0 = status
//1= X_MSB
//2= X_LSB
//3= Y_MSB
//4= Y_LSB
//5= Z_MSB
// 6= Z_LSB
{
REG_ADDRESS[i]=Wire.read(); //each time you read the write.read it gives you the next byte stored. The couter is reset on requestForm
}
// MMA8653FC gives the result in 10bits. 8bits are in _MSB, and 2 are in _LSB
// this part is used to concatenate both, and then put a sign on it (the most significant bit is giving the sign)
// the explanations are on p.14 of the 'application notes' given by freescale.
for (i=1;i<7;i=i+2)
{
accel[0] = (REG_ADDRESS[i+1]|((int)REG_ADDRESS[i]<<8))>>6; // X
if (accel[0]>0x01FF) {accel[1]=(((~accel[0])+1)-0xFC00);} // note: with signed int, this code is optional
else {accel[1]=accel[0];} // note: with signed int, this code is optional
switch(i){
case 1: axeXnow=accel[1]*resolution;
break;
case 3: axeYnow=accel[1]*resolution;
break;
case 5: axeZnow=accel[1]*resolution;
break;
}
}
}
//******************** Temperature Sensor (TMP112) Reading *****************************
void getTemperature(void)
{
long tempSum;
int tempReadingIn[2];
Wire.requestFrom(tmpAddress,2);
tempReadingIn[0] = Wire.read();
tempReadingIn[1] = Wire.read();
//it's a 12bit int, using two's compliment for negative
tempSum = ((tempReadingIn[0] << 8) | tempReadingIn[1]) >> 4;
tempC = tempSum*0.0625;
}
//********************* configure ABP ************************************************
void configureABP(void)
{
loraSerial.print("mac set deveui ");loraSerial.println(DEVICE_EUI);
Serial.print("mac set deveui ");Serial.println(DEVICE_EUI);
waitCommandResponse();
//loraSerial.print("mac set appeui ");loraSerial.println(APP_EUI);
//Serial.print("mac set appeui ");Serial.println(APP_EUI);
//waitCommandResponse();
loraSerial.print("mac set appkey ");loraSerial.println(APP_KEY);
Serial.print("mac set appkey ");Serial.println(APP_KEY);
waitCommandResponse();
loraSerial.print("mac set devaddr ");loraSerial.println(DEVICE_ADDR);
Serial.print("mac set devaddr ");Serial.println(DEVICE_ADDR);
waitCommandResponse();
loraSerial.print("mac set nwkskey ");loraSerial.println(NWK_SESSION_KEY);
Serial.print("mac set nwkskey ");Serial.println(NWK_SESSION_KEY);
waitCommandResponse();
loraSerial.print("mac set appskey ");loraSerial.println(APP_SESSION_KEY);
Serial.print("mac set appskey ");Serial.println(APP_SESSION_KEY);
waitCommandResponse();
loraSerial.println("mac save");
Serial.println("mac save");
waitCommandResponse();
loraSerial.println("mac join abp");
Serial.println("mac join abp");
waitCommandResponse();
}
#if 0 //not supported on free account
//************************ configure OTAA ************************************
void configureOTAA(void)
{
loraSerial.print("mac set deveui ");loraSerial.println(DEVICE_EUI);
Serial.print("mac set deveui ");Serial.println(DEVICE_EUI);
waitCommandResponse();
loraSerial.print("mac set appeui ");loraSerial.println(APP_EUI);
Serial.print("mac set appeui ");Serial.println(APP_EUI);
waitCommandResponse();
loraSerial.print("mac set appkey ");loraSerial.println(APP_KEY);
Serial.print("mac set appkey ");Serial.println(APP_KEY);
waitCommandResponse();
loraSerial.println("mac save");
Serial.println("mac save");
waitCommandResponse();
loraSerial.println("mac join otaa");
Serial.println("mac join otaa");
waitCommandResponse();
}
#endif
//********************* configure channels on or off ******************************
void setChannelStatus()
{
byte channelNumber=0;
for (int x=0; x<9; x++)
{
for (int b=0; b<8; b++)
{
if (bitRead(channelBank[x],b))
{
loraSerial.print("mac set ch status ");loraSerial.print(channelNumber);loraSerial.println(" on");
Serial.print("mac set ch status ");Serial.print(channelNumber);Serial.println(" on");
}
else
{
loraSerial.print("mac set ch status ");loraSerial.print(channelNumber);loraSerial.println(" off");
Serial.print("mac set ch status ");Serial.print(channelNumber);Serial.println(" off");
}
channelNumber++;
waitCommandResponse();
}
}
loraSerial.println("mac set adr off");
Serial.println("mac set adr off");
waitCommandResponse();
loraSerial.println("mac set pwridx 5");
Serial.println("Set Tx power");
waitCommandResponse();
//loraSerial.println("mac set dr 4");
//Serial.println("Set Data Rate 4");
//waitCommandResponse();
loraSerial.println("mac save");
delay(200);
}
//******************** wait for response from module *************************************
void waitCommandResponse(void)
{
unsigned long currentTime,startTime;
startTime = millis();
while (loraSerial.available() == 0)
{
currentTime = millis();
if (currentTime > (startTime + 3000)) //exit wait routine if nor response in 3 seconds
{
Serial.println("No Response from Lora Module");
return;
}
}
while (loraSerial.available())
{
Serial.write(loraSerial.read());
}
}
//************************ get configuration information from module *********************
void getConfig(void)
{
loraSerial.println("sys get ver"); //get module version
Serial.print("Module Version: ");
waitCommandResponse();
Serial.println();
loraSerial.println("sys get hweui"); //get module version
Serial.print("EUI Node Address: ");
waitCommandResponse();
Serial.println();
}