Mattias Blinge
Created July 31, 2018

Tracking the missing salmons using Sigfox IoT solution

Design and construction of a device able to transmit data packages over Sigfox-LPWAN received from an RS485 tracking unit.

41
Tracking the missing salmons using Sigfox IoT solution

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
SIGFOX Breakout board BRKWS01
×1
RS-485 Converter Module - MAX485
×1

Story

Read more

Schematics

Fritzing schematic of the circuit

Code

Program intergrated on the arduino

Arduino
//Author: Mattias Blinge
//Date: April 2018


/*-----( Import needed libraries )-----*/
#include <AltSoftSerial.h>         
// Library which enables transmission and receiving through pin 8 and 9
#include <SoftwareSerial.h>        
// Library which enables transmission and receiving through pin 10 and 11
/*-----( Declare Constants and Pin Numbers )-----*/
#define SSerialRX        10        
//Serial Receive pin TO RS485
#define SSerialTX        11        
//Serial Transmit pin TO RS485
#define SigfoxRX         8         
//Send message via Sigfox
#define SigfoxTX         9         
//Send message via Sigfox

#define SSerialTxControl 12        
//RS485 Direction control
#define RS485Transmit    HIGH
#define RS485Receive     LOW
#define NORMAL_DELAY 500           
// In milliseconds
#define SEND_INTERVAL 600000       
// Defining 10 minutes in milliseconds
#define ComputerSerial Serial

AltSoftSerial altSerial;                                
// Set up the serial port connected to the Sigfox Modem


SoftwareSerial RS485Serial(SSerialRX, SSerialTX);       
// Set up the serial port connected to TBR


/*-----( Declare Global Variables )-----*/

String sendtoTBR;
int FishInt;
unsigned long lastSendTime;

/*---------------------(Initiating  Startup Code)-------------------------- */

void setup() {
  altSerial.begin(9600);                          
  // Defining baud rate from Arduino to Sigfox Modem
  ComputerSerial.begin(9600);                     
  // Defining baud rate to computer
  RS485Serial.begin(115200);
  pinMode(SSerialTxControl, OUTPUT);              
  // Defining

  digitalWrite(SSerialTxControl, RS485Receive);   
  // Initiate Transceiver
  exitTBR();                                      
  // Making sure TBR is in listening mode
  ComputerSerial.println("Booting");      
  // Testing that communication with computer is established
  delay(10000);
  altSerial.println("AT\$SF=FFFFFF");              
  // Test for coverage at start up
  lastSendTime = millis();                        
  // Reference time for While-loop
}

/*------------------(Loop process)---------------------*/

void loop() {


/*-----( Declare Local Variables )-----*/
  int numTempInt;
  String numTemp;
  String data_received;
  String SigFoxmess;
  int IDarray0;
  int IDarray1;
  int IDarray2;
  int IDarray3;

  while ((millis() - lastSendTime) < SEND_INTERVAL) {            
  // Run program inside the loop for 10 min


    if (RS485Serial.available() > 0)                             
    // If data is received from the TBR proceed with the processing of the data
    {
      data_received = RS485Serial.readStringUntil('\n');         
      // Data is placed in a string
      String SensorCheck = getValue(data_received, ',', 6);
      if (SensorCheck == "69") {                                 
      // Find out whether the data is a "Tag detection" och "Sensory data"
        numTemp = getValue(data_received, ',', 3);               
        // Place the temperature value in String
        numTempInt = numTemp.toInt();                            
        // Convert numTemp from "string" to Integer.

      }
      else {                                                     
      // If the data received is a "tag detection"
        String IDtag1 = getValue(data_received, ',', 4);
        IDarray3 = IDarray2;
        IDarray2 = IDarray1;
        IDarray1 = IDarray0;
        IDarray0 = IDtag1.toInt();                               
        // Convert IDtag1 from "string" to Integer

      }
      getNumFishes();                                            
      // Enter "getNumFishes" to fetch total number of tag detections from TBR
      rs485Read(500);
      /*--------------(For testing purposes)----------------*/

      //ComputerSerial.println(numTempInt); 
      // Display Temperature on terminal as int
      //ComputerSerial.println(IDarray[0]);
      //ComputerSerial.println(IDarray[1]);
      //ComputerSerial.println(IDarray[2]);
      //ComputerSerial.println(IDarray[3]);
      //SigFoxmess = FishInt + numTempInt + IDarray[0]+ 
      IDarray[1] + IDarray[2] + IDarray[3];
      //ComputerSerial.println(SigFoxmess);




      //-----------(Making Sure StringFish is 16 bit)-------------
      String StringFish =  String(FishInt,  HEX);        
      // Convert value to Hexadecimal

      while (StringFish.length() < 4) {                  
      // Add "0"s from the left until length equal to 4.
        StringFish = 0 + StringFish;
      }

      //-----------(Making Sure StringTemp is 16 bit)-------------

      String StringTemp = String(numTempInt, HEX);      
      // Convert value to Hexadecimal

      while (StringTemp.length() < 4) {                 
      // Add "0"s from the left until length equal to 4.
        StringTemp = 0 + StringTemp;
      }

      //-----------(Making Sure StringIDtag0 is 16 bit)-------------

      String StringIDtag0 = String(IDarray0, HEX);      
      // Convert value to Hexadecimal

      while (StringIDtag0.length() < 4) {               
      // Add "0"s from the left until length equal to 4.
        StringIDtag0 = 0 + StringIDtag0;
      }

      //-----------(Making Sure StringIStag1 is 16 bit)-------------

      String StringIDtag1 = String(IDarray1, HEX);      
      // Convert value to Hexadecimal

      while (StringIDtag1.length() < 4) {               
      // Add "0"s from the left until length equal to 4.
        StringIDtag1 = 0 + StringIDtag1;
      }

      //-----------(Making Sure StringIStag2 is 16 bit)-------------

      String StringIDtag2 = String(IDarray2, HEX);      
      // Convert value to Hexadecimal

      while (StringIDtag2.length() < 4) {               
      // Add "0"s from the left until length equal to 4.
        StringIDtag2 = 0 + StringIDtag2;
      }

      //-----------(Making Sure StringIStag3 is 16 bit)-------------

      String StringIDtag3 = String(IDarray3, HEX);      
      // Convert value to Hexadecimal

      while (StringIDtag3.length() < 4) {               
      // Add "0"s from the left until length equal to 4.
        StringIDtag3 = 0 + StringIDtag3;
      }

      //-----------(Concatinating the Sigfox message)-----------

      SigFoxmess = String("AT\$SF=" + StringFish + StringTemp + StringIDtag0 + 
      StringIDtag1 +  StringIDtag2 + StringIDtag3);

      /*----------(For Testing Purposes)---------------*/
      //ComputerSerial.println(StringFish);   
      //Print Hex value of number of Fish passed
      //ComputerSerial.println(StringTemp);   
      //Print Hex value of last temperature read
      //ComputerSerial.println(StringIDtag0); 
      //Print Hex value of last Fish tag scanned
      //ComputerSerial.println(StringIDtag1); 
      //Print Hex value of 2:nd last Fish tag scanned
      //ComputerSerial.println(StringIDtag2); 
      //Print Hex value of 3:rd last Fish tag scanned
      //ComputerSerial.println(StringIDtag3); 
      //Print Hex value of 4:th last Fish tag scanned
      //ComputerSerial.println(SigFoxmess);   
      // Print whole message


    }
  }
  altSerial.println(SigFoxmess); 
  // Send message from Arduino to Sigfox modem.
  lastSendTime = millis();
}


//---------------FÅ FISKSTRÄNG-------------------
String getNumFishes() {                           
// Fetches the amount of tag detections made by the TBR
  sendTBR();                                      
  // Place TBR in listening mode
  rs485Send("TD?");                               
  // Send "TD?" to TBR
  String response = rs485Read(500);               
  // Read the from TBR for 500ms
  exitTBR();                                      
  // Exit TBR listening mode
  String numFishes = getValue(response, '=', 1);  
  // Process data received in "getValue" to fetch number of tag detections.
  FishInt = numFishes.toInt();                    
  // Convert numFishes from "string" to Integer.
  //ComputerSerial.println(FishInt);              
  // Prints amount of tag detections made on computer monitor
  return numFishes;

}

/*
  //---------------Get TEMPERATUR-----(Not used)------------
  String getNumTemp() {
  sendTBR();
  rs485Send("PS?0001101");
  String response = rs485Read(1000);
  exitTBR();
  String numTemp = getValue(response, ',', 6);
  //ComputerSerial.println(numTemp);
  ComputerSerial.println(response);
  return numTemp;

  }
*/
//----------------------STRING SEPARATION------------------------

String getValue(String data, char separator, int index)                   
// Splitting a string into pieces based on separation character 
// and returns the item inbetween.
{
  int found = 0;
  int strIndex[] = { 0, -1 };                                             
  // Contains the location of the beginning and end of the desired string
  int maxIndex = data.length() - 1;                                       
  // Define the length of the string

  for (int i = 0; i <= maxIndex && found <= index; i++) {                 
  // If the end of the data string is not reached and the
  // index separator is not found, proceed
    if (data.charAt(i) == separator || i == maxIndex) {                   
    // If the character at position i is equal to separator character
      found++;                                                            
      // Increment "found"
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";   
  // Returns the data between strIndex[0] and strIndex[1]
}

//---------------TBR COMMANDS-------------------------

void exitTBR() {
  rs485Send("EX!");                               
  // Command to exit Listening mode of the TBR
  rs485Read(500);                                 
  // Flush the "EX!" response
}

void sendTBR() {                                  
// Placing TBR in listening mode
  digitalWrite(SSerialTxControl, HIGH);           
  // Setting TX pin to "1"
  delay(10);
  RS485Serial.print("T");
  delay(2);                                       
  // Transmitting the sequence "TBR" to the TBR places it in listening mode
  RS485Serial.print("B");                         
  // For the TBR to interpret the sequence delays
  delay(2);                                       
  // must be placed between the letters.
  RS485Serial.print("R");
  RS485Serial.flush();
  digitalWrite(SSerialTxControl, LOW);
}


void rs485Send(String sendtoTBR) {                
// Sub function of which writes transmitted data to the TBR
  digitalWrite(SSerialTxControl, RS485Transmit);  
  // Place MAXRS485 in transmit mode
  delay(10);
  RS485Serial.print(sendtoTBR);                   
  // Transmit "s" to TBR
  RS485Serial.flush();                            
  // Wait until the all has been printed before proceeding
  digitalWrite(SSerialTxControl, RS485Receive);   
  // Place MAXRS485 in receiving mode
}

//------------------READ FROM SERALPORT---------------------------------------


String rs485Read(unsigned long timeOutMS) {
  RS485Serial.setTimeout(timeOutMS);                        
  // Wait before proceeding
  digitalWrite(SSerialTxControl, RS485Receive);             
  // Enableing receiving mode from TBR
  String readTBR = RS485Serial.readStringUntil('\n');       
  // Place data form TBR in "s"
  sendtoTBR.trim();                                         
  // Deletes white-spaces from the beginning and end of the string
  if (sendtoTBR.length() == 0) return "";                   
  // If nothing is read, return nothing.
  return readTBR;
}

//  --------------------------------------------------------------

Credits

Mattias Blinge

Mattias Blinge

1 project • 1 follower

Comments