Back to IoT Blog
Agriculture IoT 22 min read

Livestock Tracking with GPS Collars

Build GPS tracking collars for cattle and livestock. Monitor location, implement geofencing alerts, track activity levels, and detect health issues early with IoT-enabled smart collars.

System Overview

GPS livestock tracking reduces labor costs, prevents theft, and enables early disease detection. Smart collars provide real-time location data, activity monitoring, and behavioral analytics for precision livestock farming.

Key Benefits:
  • Real-time location tracking on mobile app
  • Geofencing alerts when animals leave designated areas
  • Activity monitoring for health detection
  • Heat detection through movement patterns
  • Theft prevention and recovery
  • Reduced labor for pasture checks

System Architecture

[GPS Collar] → [LoRaWAN/Cellular] → [Gateway] → [Cloud Platform]
     ↓                                              ↓
  GPS Module                                    Web Dashboard
  Accelerometer                                 Mobile App
  Battery                                       Alerts (SMS/Email)
  Temperature Sensor                            Analytics

Hardware Components

Per Collar Unit

Power Budget

Component Active Current Sleep Current Duty Cycle
ESP32 Deep Sleep - 10 ΞA 95%
GPS (Active) 50 mA - 3%
LoRa TX 120 mA - 2%
Average Current ~3.5 mA
Battery Life ~35 days (3000mAh)

Collar Assembly

Enclosure Design

Wiring Diagram

ESP32
│
├── NEO-6M GPS
│   ├── VCC → 5V (or 3.3V)
│   ├── GND → GND
│   ├── Tx → GPIO17
│   └── Rx → GPIO16
│
├── MPU6050 Accelerometer
│   ├── VCC → 3.3V
│   ├── GND → GND
│   ├── SDA → GPIO21
│   └── SCL → GPIO22
│
├── LoRa SX1276
│   ├── 3.3V → 3.3V
│   ├── GND → GND
│   ├── NSS → GPIO5
│   ├── MOSI → GPIO23
│   ├── MISO → GPIO19
│   ├── SCK → GPIO18
│   ├── RST → GPIO14
│   └── DIO0 → GPIO26
│
└── DS18B20 Temperature
    ├── VCC → 3.3V
    ├── GND → GND
    └── DATA → GPIO4 (with 4.7k pullup)
Animal Safety Considerations:
  • Ensure collar is not too tight (fit 2 fingers underneath)
  • Check for chafing weekly
  • Use breakaway collars for young animals
  • Keep weight under 3% of animal body weight
  • Remove collar if skin irritation occurs

GPS Tracker Firmware

Low-power firmware for GPS tracking collar:

#include <TinyGPS++.h>
#include <SPI.h>
#include <LoRa.h>
#include <ArduinoJson.h>
#include <esp_sleep.h>

// GPS on Hardware Serial
#define GPS_RX 17
#define GPS_TX 16
HardwareSerial gpsSerial(1);
TinyGPSPlus gps;

// LoRa pins
#define LORA_SS 5
#define LORA_RST 14
#define LORA_DIO0 26

// MPU6050
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;

// Power management
#define SLEEP_INTERVAL 300000 // 5 minutes
#define GPS_FIX_TIMEOUT 30000 // 30 seconds max for GPS fix

void setup() {
  Serial.begin(115200);
  
  // Initialize GPS
  gpsSerial.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);
  
  // Initialize LoRa
  LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);
  if (!LoRa.begin(915E6)) { // 915 MHz for US
    Serial.println("LoRa init failed!");
  }
  
  // Initialize MPU6050
  Wire.begin();
  mpu.initialize();
  if (!mpu.testConnection()) {
    Serial.println("MPU6050 connection failed");
  }
  
  // Configure deep sleep wake-up
  esp_sleep_enable_timer_wakeup(SLEEP_INTERVAL);
}

void loop() {
  // Get GPS fix
  gpsData gpsData = getGPSPosition();
  
  // Get accelerometer data
  int16_t ax, ay, az;
  mpu.getAcceleration(&ax, &ay, &az);
  float activity = calculateActivity(ax, ay, az);
  
  // Get temperature (if sensor connected)
  float temp = readTemperature();
  
  // Create payload
  StaticJsonDocument<256> doc;
  doc["lat"] = gpsData.lat;
  doc["lng"] = gpsData.lng;
  doc["activity"] = activity;
  doc["temp"] = temp;
  doc["battery"] = readBattery();
  doc["id"] = "COW_001";
  
  // Send via LoRa
  sendLoRa(doc);
  
  // Go to sleep
  Serial.println("Going to sleep...");
  esp_deep_sleep_start();
}

struct gpsData {
  float lat;
  float lng;
};

gpsData getGPSPosition() {
  unsigned long start = millis();
  gpsData data = {0, 0};
  
  while (millis() - start < GPS_FIX_TIMEOUT) {
    while (gpsSerial.available()) {
      gps.encode(gpsSerial.read());
    }
    
    if (gps.location.isUpdated()) {
      data.lat = gps.location.lat();
      data.lng = gps.location.lng();
      Serial.printf("GPS: %.6f, %.6f\n", data.lat, data.lng);
      return data;
    }
  }
  
  Serial.println("GPS timeout");
  return data;
}

float calculateActivity(int16_t ax, int16_t ay, int16_t az) {
  // Calculate vector magnitude
  float magnitude = sqrt(ax*ax + ay*ay + az*az);
  
  // Classify activity
  if (magnitude > 1500) return 3.0; // Running
  if (magnitude > 1200) return 2.0; // Walking
  if (magnitude > 900) return 1.0;  // Grazing
  return 0.5; // Resting
}

void sendLoRa(StaticJsonDocument<256>& doc) {
  char buffer[256];
  serializeJson(doc, buffer);
  
  LoRa.beginPacket();
  LoRa.print(buffer);
  LoRa.endPacket();
  
  Serial.println("LoRa packet sent");
  Serial.println(buffer);
}

float readBattery() {
  int adc = analogRead(35); // Battery voltage pin
  float voltage = adc * (3.3 / 4095.0) * 2; // Voltage divider
  return voltage;
}

float readTemperature() {
  // Implement DS18B20 reading
  return 25.0; // Placeholder
}

Connectivity Options

Comparison Table

Technology Range Power Cost Best For
LoRaWAN 5-15 km Very Low $ Large ranches, rural areas
Cellular (NB-IoT) Unlimited Low $$ Areas with cell coverage
Satellite Global High $$$$ Remote rangeland
WiFi < 100m Medium $ Feedlots, barns

LoRaWAN Gateway Setup

# Install ChirpStack Gateway Bridge
docker run -d \
  --name chirpstack-gateway \
  -p 1700:1700/udp \
  -e GATEWAY_ID=YOUR_GATEWAY_ID \
  -e SERVER=eu1.cloud.thethings.network:1700 \
  chirpstack/chirpstack-gateway-bridge

Tracking Platform

Set up real-time tracking dashboard:

Node-RED Flow for GPS Tracking

[
  {
    "id": "lorawan-input",
    "type": "udp in",
    "port": 1700,
    "datatype": "utf8"
  },
  {
    "id": "parse-gps",
    "type": "json",
    "wires": [["geofence-check"]]
  },
  {
    "id": "geofence-check",
    "type": "function",
    "func": "var lat = msg.payload.lat;\nvar lng = msg.payload.lng;\nvar inside = isInsideGeofence(lat, lng);\nmsg.inside = inside;\nif (!inside) {\n  msg.alert = 'Animal outside geofence!';\n}\nreturn msg;"
  },
  {
    "id": "store-location",
    "type": "postgres",
    "query": "INSERT INTO locations (animal_id, lat, lng, timestamp) VALUES ($1, $2, $3, NOW())"
  },
  {
    "id": "map-display",
    "type": "ui_map",
    "name": "Livestock Map",
    "lat": "payload.lat",
    "lon": "payload.lng"
  }
]

Geofencing Algorithm

function isInsideGeofence(lat, lng) {
  // Define pasture boundaries (polygon)
  const pasture = [
    {lat: 35.123, lng: -106.456},
    {lat: 35.125, lng: -106.456},
    {lat: 35.125, lng: -106.450},
    {lat: 35.123, lng: -106.450}
  ];
  
  // Ray casting algorithm
  let inside = false;
  for (let i = 0, j = pasture.length - 1; i < pasture.length; j = i++) {
    if (((pasture[i].lat > lat) !== (pasture[j].lat > lat)) &&
        (lng < (pasture[j].lng - pasture[i].lng) * (lat - pasture[i].lat) / 
         (pasture[j].lat - pasture[i].lat) + pasture[i].lng)) {
      inside = !inside;
    }
  }
  return inside;
}

Health Monitoring

Behavioral Indicators

Condition Activity Pattern Alert Threshold
Healthy Regular grazing, resting -
Sick/Injured Low activity, isolated < 2 hours movement/day
In Heat Increased movement, mounting > 3x normal activity
In Labor Restless, frequent position changes Isolated + high activity
Predator Attack Sudden sprint, scattered herd All animals running

Alert Configuration

# Alert rules for livestock monitoring
alerts:
  - name: "Geofence Breach"
    condition: "location outside pasture"
    action: "send_sms + send_email"
    priority: "high"
  
  - name: "Low Activity"
    condition: "activity < 0.5 for 24h"
    action: "send_email"
    priority: "medium"
  
  - name: "Heat Detection"
    condition: "activity > 3x baseline"
    action: "log_event"
    priority: "low"
  
  - name: "Low Battery"
    condition: "battery < 3.5V"
    action: "send_email"
    priority: "medium"
  
  - name: "No Data"
    condition: "no update for 2 hours"
    action: "send_sms"
    priority: "high"

Next Steps

Enhance your livestock tracking system:

  • Add solar panels for indefinite battery life
  • Implement mesh networking for large herds
  • Integrate with automated weighing systems
  • Add audio monitoring for distress calls
  • Connect to veterinary management software
  • Implement machine learning for disease prediction