Smart Buoy [ GPS, Radio (NRF24) and a SD Card Module ]

2,505

15

6

Introduction: Smart Buoy [ GPS, Radio (NRF24) and a SD Card Module ]

About: Somebody once thought they could fix a plug socket using chopsticks. They caused a meltdown and burnt down a town. If only they'd watched T3ch Flicks!

In this tutorial, we’ll be showing you how to get GPS data, store it on an SD card and send it somewhere using radio.

We did this so we could keep track of the location of our seaborne buoy. The radio means that we can watch it remotely and the SD card means that on the off chance something breaks and our buoy goes for a wander, we can download the data it collected during its unplanned excursion - if we're ever able to retrieve it!

Supplies:

GPS module - Amazon

SD card module - Amazon

SD card - Amazon

2 X Radio modules (NRF24L01+) - Amazon

2 X Arduino - Amazon

Step 1: Getting GPS Data

The smart buoy makes sensor measurements as it sits in the sea, including GPS location and datetime. Take a look at the schematic which shows how we set up the circuit. The GPS module communicates via serial connection, so we’re using the Arduino software serial library as well as the tiny GPS library to communicate with it. These libraries make everything super simple. Let’s take you through the code…

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(4, 3);

struct dataStruct{
  double latitude;
  double longitude;
  unsigned long date;
  unsigned long time;
}gpsData;

void setup(){
  Serial.begin(115200);
  ss.begin(9600);
}

void loop(){
  while (ss.available() > 0){
    if (gps.encode(ss.read())){
      getInfo();
      printResults();
    }
  }
}

void getInfo(){
  if (gps.location.isValid()){
    gpsData.latitude = gps.location.lat();
    gpsData.longitude = gps.location.lng();
  }
  else{
    Serial.println("Invalid location");
  }
  if (gps.date.isValid()){
    gpsData.date = gps.date.value();
  }
  else{
    Serial.println("Invalid date");
  }
  if (gps.time.isValid()){
    gpsData.time = gps.time.value();
  }
  else{
    Serial.println("Invalid time");
  }
}

void printResults(){
  Serial.print("Location: ");
  Serial.print(gpsData.latitude, 6); Serial.print(", "); Serial.print(gpsData.longitude, 6);
  Serial.print("  Date: ");
  Serial.print(gpsData.date);
  Serial.print("  Time: ");
  Serial.print(gpsData.time);
  Serial.println();
}

(Check out the video for this code at https://youtu.be/xz1ix76U28E)

Attachments

Step 2: Sending GPS Data Via Radio

Suppose the buoy is in sea taking measurements, but we want to see the data without getting our feet wet or bringing the buoy ashore. To get the measurements remotely, we’re using a radio module connected to an Arduino on both sides of the communication. In future, we will replace the receiver-side Arduino with a raspberry pi. The radio works similarly with both these interfaces so swapping them over is pretty straightforward.

The radio module communicates using SPI, which requires a few more connections than I2C but is still really easy to use because of the NRF24 library. Using the GPS module for the sensor measurements, we transmit its data from one Arduino to the other. We’re going to connect up the GPS and radio module to the Arduino and on the other side an Arduino with the radio module - have a look at the schematic.

Transmitter

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>


TinyGPSPlus gps;
SoftwareSerial ss(4, 3);
RF24 radio(8, 7); // CE, CSN


struct dataStruct{
  double latitude;
  double longitude;
  unsigned long date;
  unsigned long time;
}gpsData;


void setup() {
  Serial.begin(115200);
  ss.begin(9600);
  
  Serial.println("Setting up radio");
  //  Setup transmitter radio
  radio.begin();
  radio.openWritingPipe(0xF0F0F0F0E1LL);
  radio.setChannel(0x76);
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate(RF24_250KBPS);
  radio.stopListening();
  radio.enableDynamicPayloads();
  radio.powerUp();
  Serial.println("Starting to send");
}


void loop() {
  while (ss.available() > 0){
    if (gps.encode(ss.read())){
      getInfo();
     radio.write(&gpsData, sizeof(gpsData));
    }
  }
} 


void getInfo(){
  if (gps.location.isValid()){
    gpsData.longitude = gps.location.lng();
    gpsData.latitude = gps.location.lat();
  }
  else{
    gpsData.longitude = 0.0;
    gpsData.latitude = 0.0;
  }
  if (gps.date.isValid()){
    gpsData.date = gps.date.value();
  }
  else{
    gpsData.date = 0;
  }
  if (gps.time.isValid()){
    gpsData.time = gps.time.value();
  }
  else{
    gpsData.time = 0;
  }
}

RECEIVER

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>


RF24 radio(8, 7); // CE, CSN

struct dataStruct{
  double latitude;
  double longitude;
  unsigned long date;
  unsigned long time;
}gpsData;

void setup() {
  Serial.begin(115200);
  //  Setup receiver radio
  radio.begin();
  radio.openReadingPipe(1, 0xF0F0F0F0E1LL);
  radio.setChannel(0x76);
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate(RF24_250KBPS);
  radio.startListening();
  radio.enableDynamicPayloads();
  radio.powerUp();
}

void loop() {
  if (radio.available()) {
    radio.read(&gpsData, sizeof(gpsData));
    Serial.print("Location: ");
    Serial.print(gpsData.latitude, 6);
    Serial.print(", ");
    Serial.print(gpsData.longitude, 6);
    Serial.print("  Date: ");
    Serial.print(gpsData.date);
    Serial.print("  Time: ");
    Serial.print(gpsData.time);
    Serial.println();}
}

(Check out the video for this code at https://youtu.be/xz1ix76U28E)

Step 3: Storing Data Using an SD Card Module

The radio module is quite reliable, but sometimes you need a contingency plan in case there is a power cut on the receiver side or if the radio moves out of range. Our contingency plan is a SD card module which allows us to store the data we collect. The quantity of data being collected isn’t that large, so even a small SD card will easily be able to store a day’s worth of data.

#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>

TinyGPSPlus gps;

SoftwareSerial ss(4, 3);

struct dataStruct{
  double latitude;
  double longitude;
  unsigned long date;
  unsigned long time;
}gpsData;

void setup() {
  Serial.begin(115200);
  ss.begin(9600);
  
  if (!SD.begin(5)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");

File dataFile = SD.open("gps_data.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.println("Latitude, Longitude, Date, Time");
    dataFile.close();
  }
  else{
    Serial.println("nope can't open file");
  }
}

void loop() {
  while (ss.available() > 0){
    if (gps.encode(ss.read())){
      getInfo();
      printResults(); 
      saveInfo();
    }
  }
}

void getInfo(){
  if (gps.location.isValid()){
    gpsData.latitude = gps.location.lat();
    gpsData.longitude = gps.location.lng();
  }
  else{
    Serial.println("Invalid location");
  }
  if (gps.date.isValid()){
    gpsData.date = gps.date.value();
  }
  else{
    Serial.println("Invalid date");
  }
  if (gps.time.isValid()){
    gpsData.time = gps.time.value();
  }
  else{
    Serial.println("Invalid time");
  }
}

void printResults(){
  Serial.print("Location: ");
  Serial.print(gpsData.latitude, 6); Serial.print(", "); Serial.print(gpsData.longitude, 6);
  Serial.print("  Date: ");
  Serial.print(gpsData.date);
  Serial.print("  Time: ");
  Serial.print(gpsData.time);
  Serial.println();
}

void saveInfo(){
 File dataFile = SD.open("gps_data.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.print(gpsData.latitude);
    dataFile.print(", ");
    dataFile.print(gpsData.longitude);
    dataFile.print(", ");
    dataFile.print(gpsData.date);
    dataFile.print(", ");
    dataFile.println(gpsData.time); 
    dataFile.close();
  }
  else{
    Serial.println("nope no datafile");
  }
}

(We talk through this code in the video https://youtu.be/xz1ix76U28E)

Step 4: Sending and Storing GPS Data

{"context":{"location":{"href":"https://www.instructables.com/editInstructable/publish/E7XTBFBJYG8237E","protocol":"https:","host":"www.instructables.com","hostname":"www.instructables.com","port":"","pathname":"/editInstructable/publish/E7XTBFBJYG8237E","search":"","hash":"","origin":"https://www.instructables.com","ancestorOrigins":{}},"jQuery1124022615254677818364":1},"selector":"#editor-Object-40"}

Step 5: Thanks!

Thanks for watching this episode and following us in our journey to building our smart buoy. The next tutorial will show you how we powered the system.

Sign Up to Our Mailing List!

Part 1: Summary

Part 2: GPS NRF24 Radio and SD Card

Part 3: Scheduling Power to the Buoy

Part 4: Deploying the Buoy

Check out T3chFlicks.org for more tech-focused educational content (YouTube, Instagram, Facebook, Twitter).

Be the First to Share

    Recommendations

    • The 1000th Contest

      The 1000th Contest
    • Battery Powered Contest

      Battery Powered Contest
    • Hand Tools Only Challenge

      Hand Tools Only Challenge

    6 Discussions

    0
    panjer
    panjer

    Question 11 months ago

    excuse me, i try the same concept that connecting nrf24l01 and sdcard module at the same SCK, MOSI, and MISO, but my nrf24l01 module cannot send the data, but the sdcard module still can save data. How is it?
    thank you

    0
    IgorF2
    IgorF2

    1 year ago

    Hi there! Great job! Congrats! :D
    Do you know what's the range of the NRF module? Have you already considered using a Lora module instead? I think it has a longer range...

    1
    t3chflicks
    t3chflicks

    Reply 1 year ago

    Thanks a lot!
    We've seen some get kilometres, but we only tested up to ~60m. Yes we'll use LoRa in v2 :)

    0
    IgorF2
    IgorF2

    Reply 1 year ago

    Great! I live in a costal region and I’m planing to use Lora for remote sensing as well.
    I’ll be happy to see the next version of your project!

    0
    tytower
    tytower

    1 year ago

    I would be interested to see how you keep this going without corrosion from sea water ingress. The SD cards don't last with sea water around

    0
    t3chflicks
    t3chflicks

    Reply 1 year ago

    It’s in a water right buoy so hopefully none but we’ll see when we leave it out in the ocean for a bit