RAK2270 IOT Course

I am just starting my Advanced IOT course using the RAK2270 Sticker Tracker Flexible Development boards. It will take a few weeks/months to get everything working but I am really excited about it.

The main link for the RAK part is here maker100-eco

and the code I just finished today teaches about RAK AT commands and the API see code here and below

This code switches every 30 seconds between LoRaWan and LoRa P2P modes and shows the AT commands with API variations for many common uses. This is how I will get my students familiar with the device.

They will use AT commands to send me messages over P2P. Some students will be able to setup LoRaWan networks just with this code.

If you have some time @carlrowan can you see if I have missed any of the main LoRaWan or LoRa “AT” commands? I know there are tons more but any that beginners should be aware of that are missing?

/*************************************
 *
 * Rak Hack made to print the important RAK "AT" commands for both LoRaWan and LoRa P2P settings
 * Documentation of AT and RUI3 API at https://docs.rakwireless.com/RUI3/Serial-Operating-Modes/AT-Command-Manual/#content
 *
*************************************/

void myBuffPrint(uint8_t* myBuff, uint8_t myLen){
    for (int i = 0; i < myLen; i++) {
      if (myBuff[i] < 0x10) {
        Serial.print("0");
      }
    Serial.print(myBuff[i], HEX);
  }
}


void myLoraPrint(){

    Serial.println();
    Serial.println("LoRa P2P Information RAK HACK");
    Serial.println("------------------------------------------------------");
    Serial.printf("AT+HWMODEL=? Hardware ID: %s\r\n",        api.system.chipId.get().c_str());
    Serial.printf("AT+HWID=?    Model ID: %s\r\n",           api.system.modelId.get().c_str());
    Serial.printf("AT+APIVER=?  RUI API Version: %s\r\n",    api.system.apiVersion.get().c_str());
    Serial.printf("AT+VER=?     Firmware Version: %s\r\n",   api.system.firmwareVersion.get().c_str());
    Serial.printf("AT+CLIVER=?  AT Command Version: %s\r\n", api.system.cliVersion.get().c_str());
    Serial.println();
    Serial.println("At Commands: AT? for help, ATE for echo , ATZ for reset, AT+DEBUG=1 for debug mode");
    Serial.println("At Commands: AT+BOOT to upload code, AT+RUN reset after boot mode");
    Serial.println("At Commands: AT+P2P=?  gives most of the P2P settings");
    Serial.println("At Commands: AT+PSEND=61624142203132      P2P send data   'abAB 12' ");    
    Serial.println("At Commands: AT+PRECV=?   Codes for P2P received data:  try 0= only send, 30000=receive for 30 s, 65533 can receive and send, 65534=wait for one receive then can send, 65535 = only receive");    
   // Serial.println("At Commands: AT+ENCRY=?   P2P mode encryption. 0 default no encryption, 1 encryption");    
    Serial.println();
    
    Serial.printf("AT+NWM=?     network working mode (0 = P2P_LORA, 1 = LoRaWAN, 2 = P2P_FSK)  %d\r\n", api.lorawan.nwm.get());


    Serial.printf("AT+PFREQ=?   P2P mode frequency   AT+PFREQ=915000000: %d\r\n", api.lorawan.pfreq.get());
    Serial.printf("AT+PSF=?     P2P mode spreading factor  5-12: %d\r\n", api.lorawan.psf.get());
    Serial.printf("AT+PBW=?     P2P mode bandwidth      (LORA: 0 = 125, 1 = 250, 2 = 500, 3 = 7.8, 4 = 10.4, 5 = 15.63, 6 = 20.83, 7 = 31.25, 8 = 41.67, 9 = 62.5 FSK: 4800-467000): %d\r\n", api.lorawan.pbw.get());
    Serial.printf("AT+PCR=?     P2P mode code rate     (0=4/5, 1=4/6, 2=4/7, 3=4/8): %d\r\n", api.lorawan.pcr.get());
    Serial.printf("AT+PPL=?     P2P mode preamble length     (5-65535)   default = 8: %d\r\n", api.lorawan.ppl.get());
  //  Serial.printf("AT+PRECV=?   Codes for P2P received data: %d\r\n", api.lorawan.precv());
    Serial.printf("AT+ENCRY=?   P2P mode encryption. 0 default no encryption, 1 encryption: %d\r\n", api.lorawan.encry.get());
    //  Serial.printf("AT+PSEND=61624142203132      P2P send data   'abAB 12' %d\r\n", api.lorawan.psend(sizeof(61624142203132),61624142203132 ));





    Serial.println();
    Serial.println("Switch to LoRaWan mode and resetting in 30s");
    delay(30000);
    api.lorawan.nwm.set(1);
    api.system.reboot();
}




void myLoRaWanPrint(){
    uint8_t buff[8];
    uint8_t buffBig[16];

    Serial.println();
    Serial.println("LoRaWan Information RAK HACK");
    Serial.println("------------------------------------------------------");
    Serial.printf("AT+HWMODEL=? Hardware ID: %s\r\n",        api.system.chipId.get().c_str());
    Serial.printf("AT+HWID=?    Model ID: %s\r\n",           api.system.modelId.get().c_str());
    Serial.printf("AT+APIVER=?  RUI API Version: %s\r\n",    api.system.apiVersion.get().c_str());
    Serial.printf("AT+VER=?     Firmware Version: %s\r\n",   api.system.firmwareVersion.get().c_str());
    Serial.printf("AT+CLIVER=?  AT Command Version: %s\r\n", api.system.cliVersion.get().c_str());
    Serial.println();
    Serial.println("At Commands: AT? for help, ATE for echo , ATZ for reset, AT+DEBUG=1 for debug mode");
    Serial.println("At Commands: AT+BOOT to upload code, AT+RUN reset after boot mode, AT+JOIN attempts to join");
    Serial.println("At Commands: AT+SEND=12:61624142203132     send data   'abAB 12'   11 byte or less send");
    Serial.println("At Commands: AT+LPSEND=2:0:03683C0467067C07730010080200C8   long send     ");
    Serial.println();

    Serial.printf("AT+NWM=?     network working mode (0 = P2P_LORA, 1 = LoRaWAN, 2 = P2P_FSK):   %d\r\n", api.lorawan.nwm.get());





    api.lorawan.deui.get(buff, 8);
    Serial.print("AT+DEVEUI=?  device EUI 8 bytes       ");
    myBuffPrint(buff, 8);
    Serial.println();

    api.lorawan.appeui.get(buff, 8);
    Serial.print("AT+APPEUI=?  application EUI 8 bytes  ");
    myBuffPrint(buff, 8);
    Serial.println();

    api.lorawan.appkey.get(buffBig, 16);
    Serial.print("AT+APPKEY=?  application key 16 bytes ");
    myBuffPrint(buffBig, 16);
    Serial.println();

    uint16_t maskBuff;
    api.lorawan.mask.get(&maskBuff);
    Serial.printf("AT+MASK=?    Channel mask = %04X\r\n", maskBuff);
    Serial.println();


    Serial.printf("AT+NJM=?     network join mode (0 = ABP, 1 = OTAA):   %d\r\n", api.lorawan.njm.get());
    Serial.printf("AT+NJS=?     network join status (0 = not joined, 1 = joined): %d\r\n", api.lorawan.njs.get());




    
    Serial.printf("AT+DR=?      get the data rate US915 0-4: %d\r\n", api.lorawan.dr.get());
    Serial.printf("AT+JOIN      Join to the network through a gateway: %d\r\n", api.lorawan.join());
  //  Serial.printf("AT+SEND=12:112233 Send data in port: hex format (make sure no space at the end, 11 byte limit) %d\r\n", api.lorawan.send(sizeof(112233), 112233, 12););
 //   Serial.printf("AT+LPSEND=2:0:03683C0467067C07730010080200C8 Long send allows more bytes, might have issues %d\r\n", api.lorawan.lpsend(2, 0, 03683C0467067C07730010080200C, sizeof(03683C0467067C07730010080200C)););
    Serial.printf("AT+CLASS=?   Description: LoRa Class 0=A, 1=B, 2=C: %d\r\n", api.lorawan.deviceClass.get());
    Serial.printf("AT+TXP=?     Transmitting power (0 = default highest TX power, 1 - 14 =  TX power): %d\r\n", api.lorawan.txp.get());
    Serial.printf("AT+RSSI=?    Gives the RSSI strength of the last connection: %d\r\n", api.lorawan.rssi.get());
  //  Serial.printf("AT+ARSSI=? Description: Inquire all channel RSSI: %d\r\n", api.lorawan.arssi.get());
  
    Serial.printf("AT+BAND=?    Description: Active region (1 = CN470, 4 = EU868, 5 = US915, 6 = AU915): %d\r\n", api.lorawan.band.get());
    Serial.printf("AT+CFS=?     status of last send command: %d\r\n", api.lorawan.cfs.get());
   // Serial.printf("AT+DR=?    get the data rate: %d\r\n", api.lorawan.dr.get());
  //  Serial.printf("AT+RECV=?  Last received data in hex mode (make sure no space at the end) %d\r\n", api.lorawan.dr.get());

   






    Serial.println();
    Serial.println("Switch to LoRa mode and resetting in 30s");
    delay(30000);
    api.lorawan.nwm.set(0);
    api.system.reboot();

}




void setup(){
    Serial.begin(115200);

 
    if(api.lorawan.nwm.get() == 0) {    // LoRa
       myLoraPrint();
     } else   {
       myLoRaWanPrint(); 
    }


}


void loop(){
  // nothing useful here
}

1 Like

My simple Acceleration example:

/******************************************************************************
*
* Rak-IMU Simple RAK2270 acceleration example
*
* Note: Serial speed is important 115200 is the best to use.
******************************************************************************/

#include "SparkFunLIS3DH.h"
#include "Wire.h"
#include "SPI.h"

LIS3DH myIMU(I2C_MODE, 0x19); //Default constructor is I2C, addr 0x19.

void setup() {

  Serial.begin(115200);
  delay(1000); //relax...
  Serial.println("Processor came out of reset.");

  myIMU.settings.adcEnabled = 1;
  myIMU.settings.tempEnabled = 1;
  myIMU.settings.accelSampleRate = 50;  // Hz.  Can be: 0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000 Hz
  myIMU.settings.accelRange = 4;        // Max G force readable.  Can be: 2, 4, 8, 16
  myIMU.settings.xAccelEnabled = 1;
  myIMU.settings.yAccelEnabled = 1;
  myIMU.settings.zAccelEnabled = 1;

  myIMU.begin();

}


void loop(){
  float myX, myY, myZ;
  
  // do math conversions here if you want
  myX = myIMU.readFloatAccelX()*9.8 + 0.0;
  myY = myIMU.readFloatAccelY()*9.8 + 0.0;
  myZ = myIMU.readFloatAccelZ()*9.8 + 0.0;

 Serial.println("x; " + String(myX, 2) + ", y; " + String(myY, 2) + ",z; " + String(myZ, 2) );

  delay(3000);
}

1 Like

I left to the end a simple temperature, humidity sketch, thinking that would be some easy example written somewhere, but actually having troubles finding anything. the firmware has a confusing temperature example but surely there must be an easier method.

Anyone perhaps @carlrowan got a simple temperature, humidity example for the RAK2270 ?

Thanks a lot @jerteach for the share and putting all these trainings documents avalaible for everyone :+1: :+1:

1 Like

Thanks @vincen I should be making a few videos to go along with the sketches once my students have confirmed that everything works.

The video playlist will be here https://www.youtube.com/watch?v=Eye5zlfl3I8&list=PL57Dnr1H_egsfctG_K8AQ9uGhaLsTth6x

1 Like

OK so I got NTC temperature working, but as far as I can tell I should also be able to get SHTC3 temp and humididty working. Also some strange things with the IMU. It looks like both a 3 axis (works) and 9 axis (not yet) IMU are on board.

Anyway here is the NTC temp code extracted from the firmware. Still looking for EEPROM example code.




#define NTC_EN    WB_A1
#define NTC_ADC   WB_A0

/**
 * @brief Get Temperature from NTC
 * Here is a ln relationship. T = 84.987-25.18*ln(10*V/(3.3-V))
 */
float getTemperature() 
{
  float max, ref;
  
  pinMode(NTC_EN, OUTPUT);
  digitalWrite(NTC_EN, HIGH);
  delay(200);

  analogReadResolution(10);
  pinMode(NTC_EN, OUTPUT);

    switch (udrv_adc_get_resolution()) {
        case UDRV_ADC_RESOLUTION_6BIT:
        {
            max = 64.0;
            break;
        }
        case UDRV_ADC_RESOLUTION_8BIT:
        {
            max = 256.0;
            break;
        }
        case UDRV_ADC_RESOLUTION_10BIT:
        default:
        {
            max = 1024.0;
            break;
        }
        case UDRV_ADC_RESOLUTION_12BIT:
        {
            max = 4096.0;
            break;
        }
        case UDRV_ADC_RESOLUTION_14BIT:
        {
            max = 16384.0;
            break;
        }
    }

    switch (udrv_adc_get_mode()) {
        case UDRV_ADC_MODE_DEFAULT:
        default:
        {
            #ifdef rak11720
            ref = 2.0;
            #else
            ref = 3.6;
            #endif
            break;
        }
        #ifdef rak11720
        case UDRV_ADC_MODE_1_5:
        {
            ref = 1.5;
            break;
        }
        #else
        case UDRV_ADC_MODE_3_3:
        {
            ref = 3.3;
            break;
        }
        case UDRV_ADC_MODE_3_0:
        {
            ref = 3.0;
            break;
        }
        case UDRV_ADC_MODE_2_4:
        {
            ref = 2.4;
            break;
        }
        case UDRV_ADC_MODE_1_8:
        {
            ref = 1.8;
            break;
        }
        case UDRV_ADC_MODE_1_2:
        {
            ref = 1.2;
            break;
        }
        #endif
    }

  float vbat = api.system.bat.get();
  uint16_t tv = analogRead(NTC_ADC);
  float tv2 = (tv * vbat)/max;
  float tmp = 84.987 - 25.18 *log(10*tv2/(vbat-tv2));
  
  delay(100);
  digitalWrite(NTC_EN, LOW);
  
  return tmp;
}

/**
 * @brief Calibrate Temperature
 * 1st: y = (0.00312f * x^2) + (0.927f * x) - 1.2f
 * 2nd: y = (0.976f * x) - 1.11
 */
float calibrateTemperature(float temp)
{
  float temp2 = (0.00312f * temp * temp) + (0.927f * temp) - 1.2f;
  temp2 = (0.976f * temp2) - 1.11;
  return temp2;
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

}

void loop() {

  float voltage = api.system.bat.get();
  Serial.printf("Battery Voltage: %2.2fV, ", voltage);
  float tempT = getTemperature();
  float temperature = calibrateTemperature(tempT);
  Serial.printf("NTC_Temp.: %4.2f Degrees Celcius\r\n", temperature);
  delay(5000);

}

Arrgh! I have disabled 2 boards so far. One my own fault and the other just trying to install the DR_ROBOT_BMX160 library 9 dof IMU example.

So I started a thread about using the RAKDAP1 as a debugger here

Hi @jerteach ,

Thank you for your wonderful work here for the RAK2270! :star_struck:

Regarding the Temperature-Humidity sensor and the 9-axis IMU, these are not mounted on the RAK2270. Those are only provisions. So you are correct on what you see that you can only have NTC and the 3-axis accelerometer working.

1 Like

Thanks @carlrowan that clears up some confusion on my part.

STM32CubeProgrammer with RAK2270

So I have a few more videos about the RAK2270 on my youtube playlist.

Reminder these are not full online courses, they are more for if a student was away or missed a step during my in-class demonstration. I find if I try to make perfect online Robotics course videos I have to explain every step and the videos quickly become boring and students will not watch them.

The play list is here with this video showing how to switch between LoRa P2P and LoRaWan and teaches about the AT commands with the code showing several RUI3 API statements.