Portable vehicle to monitoring marine pollution

Portable vehicle to monitor from the condition of water pollution in the water

Portable vehicle to monitoring marine pollution

Things used in this project

 

Hardware components

HARDWARE LIST
1 Gravity: Analog Turbidity Sensor DFRobot
2 Seeed Studio Wio Terminal
1 Seeed Studio Grove - LoRa Radio 433MHz
1 PH-4502C DIYMORE
1 Seeed Studio Seeed XIAO RP2040
1 PX4 Pixhawk
1 Brushless motor
1 HobbyKing 30A (2~4S) ESC 3A

Software apps and online services

 

Arduino IDE

 

Edge Impulse Studio

Story

 

Story

 

Currently, marine habitats are under threat of pollution that impacts on many human activities and human life. The increasing concern about pollution levels in the oceans and coastal areas has led to various approaches to measuring and reducing marine pollution, in order to achieve sustainable seawater quality. There are several methods for monitoring ocean conditions such as remote sensing by satellite, ocean buoy monitoring. But I want to add a new method using portable vehicles to get data on marine pollution conditions.

 

Solution

 

some of the existing solution methods are static installations such as ocean bouy installations, so that the conditions for other areas cannot be tracked. So with a portable vehicle makes it easy to take measurements in accordance with the direction given to the vehicle. so it can easily track the condition of marine pollution.

 

Preparation

 

For portable vehicles, I made a mini hull boat equipped with a waypoint for automatic features like the Autonomous Surface Vehicle (ASV) or manual with remote control to direct the desired location.

 

mini hull boat

 

mini hull boat

I built mini hull boat from 3d Print with specification

Pixhawk ControllerESCBrushless MotorGPSReceiver ControllerRemote ControllerTelemetry 

inside mini hull boat

 

inside mini hull boat

For System monitoring, I built 2 devices

Device in Mini Hull

Turbidity SensorPH Meter and Temperature SensorSeed XIAO RP240Lora

Device in Ground Station

WIO TerminalLora

 

 

 

Section Test

 

1.Turbidity Sensor Test

 

to read turbidity sensor use Analog Pin (A0) in seeed xiao RP2040

 


 

CODE
int sensorPin = A0;
float volt;

void setup()
{
  Serial.begin(9600);
 }
 
void loop()
{
    
    volt = 0;
    for(int i=0; i<800; i++)
    {
        volt += ((float)analogRead(sensorPin)/1023)*5;
    }
    volt = volt/800;
    volt = round_to_dp(volt,2);

    Serial.print(volt);
    delay(10);
}

float round_to_dp( float in_value, int decimal_place )
{
  float multiplier = powf( 10.0f, decimal_place );
  in_value = roundf( in_value * multiplier ) / multiplier;
  return in_value;
}

Clean Water

Result Voltage if Clean Water

Dirty Water

Result Voltage if Dirty Water

2.PHSensor Test

 

to read turbidity sensor use Analog Pin (A1) in seeed xiao RP2040

CODE
const int analogInPin = A1; 
int sensorValue = 0; 
unsigned long int avgValue; 
float b;
int buf[10],temp;
void setup() {
 Serial.begin(9600);
}

void loop() {
 for(int i=0;i<10;i++) 
 { 
  buf[i]=analogRead(analogInPin);
  delay(10);
 }
 for(int i=0;i<9;i++)
 {
  for(int j=i+1;j<10;j++)
  {
   if(buf[i]>buf[j])
   {
    temp=buf[i];
    buf[i]=buf[j];
    buf[j]=temp;
   }
  }
 }
 avgValue=0;
 for(int i=2;i<8;i++)
 avgValue+=buf[i];
 float pHVol=(float)avgValue*3.3/1024/6;
 float phValue = -5.70 * pHVol + 21.34;
 Serial.print("PH = ");
 Serial.println(phValue);

 delay(20);
}

For test PH, I use 3 sample and PH universal indicator paper

 

3 sample with PH Universal Indicator Paper

 

3 sample with PH Universal Indicator Paper

 

Result PH Test

Fig 1. Test PH Clean Water

Fig 2. Test PH Clean Water (avg 7.0)

Fig 3. Test PH Clean Water with universal paper (indicator 7)

Fig 4. Test PH Soap Water

Fig 5. Test PH Soap Water (near 8)

Fig 6. Test PH Soap Water with universal paper (indicator 8)

Fig 7. Test PH Dirty Water

 

Fig 8. Test PH Dirty Water (Near 6)

 

Fig 9. Test PH Dirty Water with universal paper (indicator 6)

 

3.WaterproofTemperatureSensor Test

 

to read temperature sensor use digital Pin (2) in seeed xiao RP2040, and use resistor 4, 7K (data with vcc)

CODE
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is conntec to the Arduino digital pin 4
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

void setup(void)
{
  // Start serial communication for debugging purposes
  Serial.begin(9600);
  // Start up the library
  sensors.begin();
}

void loop(void){ 
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  
  Serial.print("Celsius temperature: ");
  // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
  Serial.print(sensors.getTempCByIndex(0)); 
  Serial.print(" - Fahrenheit temperature: ");
  Serial.println(sensors.getTempFByIndex(0));
  delay(1000);
}

Result temperature test

 

Temperature Test

 

Result Temperature Test

4. WIO Terminal Test

Wio Terminal is amazing device at the moment, I interest to use wio terminal in many project, because is easy to make everything.

5. Lora Test P2P

 

for lora test P2P, I use 2 lora to connect in wio terminal and seeed xiao, every 2 second send 4 data

Test Lora Transmitter

CODE
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial e5(9, 10); 
int data1=0;
int data2=0;
int data3=0; 
int data4=0; 

static char recv_buf[512];
static bool is_exist = false;

static int at_send_check_response(char *p_ack, int timeout_ms, char *p_cmd, ...)
{
    int ch = 0;
    int index = 0;
    int startMillis = 0;
    va_list args;
    memset(recv_buf, 0, sizeof(recv_buf));
    va_start(args, p_cmd);
    e5.printf(p_cmd, args);
    Serial.printf(p_cmd, args);
    va_end(args);
    delay(200);
    startMillis = millis();
 
    if (p_ack == NULL)
    {
        return 0;
    }
 
    do
    {
        while (e5.available() > 0)
        {
            ch = e5.read();
            recv_buf[index++] = ch;
            Serial.print((char)ch);
            delay(2);
        }
        if (strstr(recv_buf, p_ack) != NULL)
        {
            return 1;
        }
    } while (millis() - startMillis < timeout_ms);
    return 0;
}

static int node_send(uint32_t timeout)
{
    static uint16_t count = 0;
    int ret = 0;
    char data[32];
    char cmd[128];
    
    memset(data, 0, sizeof(data));
    sprintf(data, "%04X,%04X,%04X,%04X", data1, data2, data3,data4);
    sprintf(cmd, "AT+TEST=TXLRPKT,\"5345454544%s\"\r\n", data);
    ret = at_send_check_response("TX DONE", 2000, cmd);
    if (ret == 1)
    {
        Serial.print("Sent successfully!\r\n");
    }
    else
    {
        Serial.print("Send failed!\r\n");
    }
    data1++;
    data2=data2+5;
    data3=data3+10;
    data4=data4+20;
    return ret;
}
 
void setup(void)
{
    Serial.begin(115200);
    // while (!Serial);
    e5.begin(9600);
    uint16_t error;
    char errorMessage[256];
    Serial.print("ping pong communication!\r\n");
    if (at_send_check_response("+AT: OK", 100, "AT\r\n"))
    {
        is_exist = true;
        at_send_check_response("+MODE: TEST", 1000, "AT+MODE=TEST\r\n");
        at_send_check_response("+TEST: RFCFG", 1000, "AT+TEST=RFCFG,866,SF12,125,12,15,14,ON,OFF,OFF\r\n");
        delay(200);
    }
    else
    {
        is_exist = false;
        Serial.print("No E5 module found.\r\n");
    }
}
 
void loop(void)
{
    if (is_exist)
    {
        node_send(2000);
        delay(3000);    
    }
}

Test Lora Receiver

CODE
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <Wire.h>
#include <SoftwareSerial.h>
SoftwareSerial e5(0, 1);
static char recv_buf[512];
static bool is_exist = false;


TFT_eSPI tft;
TFT_eSprite spr = TFT_eSprite(&tft);  //sprite
static int at_send_check_response(char *p_ack, int timeout_ms, char *p_cmd, ...)
{
    int ch = 0;
    int index = 0;
    int startMillis = 0;
    va_list args;
    memset(recv_buf, 0, sizeof(recv_buf));
    va_start(args, p_cmd);
    e5.printf(p_cmd, args);
    Serial.printf(p_cmd, args);
    va_end(args);
    delay(200);
    startMillis = millis();
 
    if (p_ack == NULL)
    {
        return 0;
    }
    do
    {
        while (e5.available() > 0)
        {
            ch = e5.read();
            recv_buf[index++] = ch;
            Serial.print((char)ch);
            delay(2);
        }
 
        if (strstr(recv_buf, p_ack) != NULL)
        {
            return 1;
        }
 
    } while (millis() - startMillis < timeout_ms);
    return 0;
}
 
static int recv_prase(void)
{
    char ch;
    int index = 0;
    memset(recv_buf, 0, sizeof(recv_buf));
    while (e5.available() > 0)
    {
        ch = e5.read();
        recv_buf[index++] = ch;
        Serial.print((char)ch);
        delay(2);
    }
 
    if (index)
    {
        char *p_start = NULL;
        char data[32] = {
            0,
        };
        int rssi = 0;
        int snr = 0;
 
        p_start = strstr(recv_buf, "+TEST: RX \"5345454544");
        if (p_start)
        {
            
            spr.fillSprite(TFT_BLACK);
            p_start = strstr(recv_buf, "5345454544");
            if (p_start && (1 == sscanf(p_start, "5345454544%s,", data)))
            {
                data[16] = 0;
                int data1;
                int data2;
                int data3;
                int data4;
                char *endptr;
                char *endptr1;
                char *endptr2;
                char *endptr3;
                char dataarray1[5] = {data[0], data[1],data[2], data[3]};
                char dataarray2[5] = {data[4], data[5], data[6], data[7]};
                char dataarray3[5] = {data[8], data[9], data[10], data[11]};
                char dataarray4[5] = {data[12], data[13],data[14], data[15]};
                
                data1 = strtol(dataarray1, &endptr, 16);
                data2 = strtol(dataarray2, &endptr1, 16);
                data3 = strtol(dataarray3, &endptr, 16);
                data4 = strtol(dataarray4, &endptr1, 16);
 
                  spr.createSprite(55, 30);
                  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
                  spr.setTextColor(TFT_WHITE);
                  spr.drawNumber(data1, 0, 0, 1);
                  spr.setTextColor(TFT_GREEN);
                  spr.pushSprite((tft.width() / 2) - 1, 100);
                  spr.deleteSprite();
                
                  spr.createSprite(55, 30);
                  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
                  spr.setTextColor(TFT_WHITE);
                  spr.drawNumber(data2, 0, 0, 1);
                  spr.pushSprite(((tft.width() / 2) + (tft.width() / 2) / 2), 97);
                  spr.deleteSprite();
                
                  spr.createSprite(55, 30);
                  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
                  spr.setTextColor(TFT_WHITE);
                  spr.drawNumber(data3, 0, 0, 1);
                  spr.pushSprite((tft.width() / 2) - 1, (tft.height() / 2) + 67);
                  spr.deleteSprite();
                
                  spr.createSprite(55, 30);
                  spr.setFreeFont(&FreeSansBoldOblique12pt7b);
                  spr.setTextColor(TFT_WHITE);
                  spr.drawNumber(data4, 0 , 0, 1);
                  spr.pushSprite(((tft.width() / 2) + (tft.width() / 2) / 2), (tft.height() / 2) + 67);
                  spr.deleteSprite();
                Serial.print("data received displaying on the wio terminal");
                Serial.print("\r\n");
                
            }
 
            p_start = strstr(recv_buf, "RSSI:");
            if (p_start && (1 == sscanf(p_start, "RSSI:%d,", &rssi)))
            {
                String newrssi = String(rssi);
          
                Serial.print(rssi);
                Serial.print("\r\n");

            }
            p_start = strstr(recv_buf, "SNR:");
            if (p_start && (1 == sscanf(p_start, "SNR:%d", &snr)))
            {
                Serial.print(snr);
                Serial.print("\r\n");

                
            }
            return 1;
        }
    }
    return 0;
}
 
static int node_recv(uint32_t timeout_ms)
{
    at_send_check_response("+TEST: RXLRPKT", 1000, "AT+TEST=RXLRPKT\r\n");
    int startMillis = millis();
    do
    {
        if (recv_prase())
        {
            return 1;
        }
    } while (millis() - startMillis < timeout_ms);
    return 0;
}
void setup() {
    Serial.begin(115200);
    tft.begin();
    tft.setRotation(3);

    e5.begin(9600);
    Serial.print("Receiver\r\n");
    
    if (at_send_check_response("+AT: OK", 100, "AT\r\n"))
    {
        is_exist = true;
        at_send_check_response("+MODE: TEST", 1000, "AT+MODE=TEST\r\n");
        at_send_check_response("+TEST: RFCFG", 1000, "AT+TEST=RFCFG,866,SF12,125,12,15,14,ON,OFF,OFF\r\n");
        delay(200);
    }
    else
    {
        is_exist = false;
        Serial.print("No E5 module found.\r\n");
    }

  //Head
  tft.fillScreen(TFT_BLACK);
  tft.setFreeFont(&FreeSansBoldOblique18pt7b);
  tft.setTextColor(TFT_WHITE);
  tft.drawString("Test Receiver", 40, 10 , 1);

  //Line
  for (int8_t line_index = 0; line_index < 5 ; line_index++)
  {
    tft.drawLine(0, 50 + line_index, tft.width(), 50 + line_index, TFT_WHITE);
  }

  //Additional
  tft.drawRoundRect(5, 60, (tft.width() / 2) - 20 , tft.height() - 65 , 10, TFT_WHITE); // L1
  tft.setFreeFont(&FreeSansBoldOblique12pt7b);
  tft.setTextColor(TFT_RED);
  tft.drawString("Condition", 12 , 65 , 1);
  tft.setTextColor(TFT_GREEN);
  tft.drawString("Normal", 35, 128, 1);

  //data1
  tft.drawRoundRect((tft.width() / 2) - 10  , 60, (tft.width() / 2) / 2 , (tft.height() - 65) / 2 , 10, TFT_WHITE); // s1
  tft.setFreeFont(&FreeSansBoldOblique9pt7b);
  tft.setTextColor(TFT_RED) ;
  tft.drawString("Data1", (tft.width() / 2) - 1  , 70 , 1); // Print the test text in the custom font

  //data2
  tft.drawRoundRect(((tft.width() / 2) + (tft.width() / 2) / 2) - 5  , 60, (tft.width() / 2) / 2 , (tft.height() - 65) / 2 , 10, TFT_WHITE); // s2
  tft.setFreeFont(&FreeSansBoldOblique9pt7b);
  tft.setTextColor(TFT_RED);
  tft.drawString("Data2", ((tft.width() / 2) + (tft.width() / 2) / 2)   , 70 , 1); // Print the test text in the custom font

  //data3
  tft.drawRoundRect((tft.width() / 2) - 10 , (tft.height() / 2) + 30, (tft.width() / 2) / 2 , (tft.height() - 65) / 2 , 10, TFT_WHITE); // s3
  tft.setFreeFont(&FreeSansBoldOblique9pt7b);
  tft.setTextColor(TFT_RED) ;
  tft.drawString("Data3", (tft.width() / 2) - 1 , (tft.height() / 2) + 40 , 1); // Print the test text in the custom font

  //data4
  tft.drawRoundRect(((tft.width() / 2) + (tft.width() / 2) / 2) - 5  , (tft.height() / 2) + 30, (tft.width() / 2) / 2 , (tft.height() - 65) / 2 , 10, TFT_WHITE); // s4
  tft.setFreeFont(&FreeSansBoldOblique9pt7b);
  tft.setTextColor(TFT_RED) ;
  tft.drawString("Data4", ((tft.width() / 2) + (tft.width() / 2) / 2)   , (tft.height() / 2) + 40 , 1); // Print the test text in the custom font

}

void loop() {
   if (is_exist)
    {
        node_recv(2000);
    }
}

Result p2p

 

 

 

 

Collecting Data

 

After all sensor and communication P2P working well, next step collecting data sensor. In this project, data collecting is carried out using a data forwarder to edge impulse.

 

Create Edge Impulse Account

 

 

install the following software:

 

Node.js v12 or higher. Arduino CLI The Edge Impulse CLI and a serial monitor. (Install by opening node.js command prompt)
CODE
npm install -g edge-impulse-cli

Install edge impulse CLI

 

Install edge impulse CLI done

Install data forwarder (The data forwarder is used to easily relay data from any device to Edge Impulse over serial. Devices write sensor values over a serial connection, and the data forwarder collects the data, signs the data and sends the data to the ingestion service)
CODE
edge-impulse-data-forwarder

For collecting data with forwarder data, this link is very helpfully

Collecting data processed

 

 

fig 2. give device name

fig 3. Give name in device

fig 4. Edge Impulse WIO Terminal devices

 

fig 5. Data Acquistion to collect class data

 

 

fig 6.  Collect data clean water

 

Fig 7. Collect data dirty water

 

 

 

Fig 2. Create Impulse

 

fig 1. flatten 1

Fig 2. flatten 2

 

Fig 3. flatten 3

 

Fig 4. flatten 4

 

 

Fig 5. flatten 5

 

Fig 1. NN Clasifier

 

Fig 2. NN Classifier

 

 

Fig 1. Click Arduino

 

fig 2. Buld Deployment

 

Fig 3. Built Arduino Library Completed

 

Open Arduino IDE than import library was build by edge impulse, open example and edit in raw_feature_get_data

CODE
/* Edge Impulse Arduino examples
 * Copyright (c) 2021 EdgeImpulse Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/* Includes ---------------------------------------------------------------- */
#include <sekolahrobot-project-1_inferencing.h>
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

SoftwareSerial e5(9, 10); 
const int analogInPin = A1; 
int sensorPin = A0;
float volt;
int sensorValue = 0; 
unsigned long int avgValue;
float pHVol;
float phValue; 
float b;
int buf[10],temp;

#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float tempC;

static const float features[114] = {};

int raw_feature_get_data(size_t offset, size_t length, float *out_ptr) {
  float features[114];
  readPH();
  readTurbidity();
  readSuhu();
  
  for (byte i = 0; i < 114; i = i + 3)
  {
    features[i]=volt;
    features[i+1]=phValue;
    features[i+2]=tempC;
    delay(200);
  }
  memcpy(out_ptr, features + offset, length * sizeof(float));
  return 0;
}


void setup()
{
    // put your setup code here, to run once:
    Serial.begin(115200);
    // comment out the below line to cancel the wait for USB connection (needed for native USB)
    while (!Serial);
    Serial.println("Edge Impulse Inferencing Demo");
}

/**
 * @brief      Arduino main function
 */
void loop()
{
    ei_printf("Edge Impulse standalone inferencing (Arduino)\n");

    if (sizeof(features) / sizeof(float) != EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE) {
        ei_printf("The size of your 'features' array is not correct. Expected %lu items, but had %lu\n",
            EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, sizeof(features) / sizeof(float));
        delay(1000);
        return;
    }

    ei_impulse_result_t result = { 0 };

    // the features are stored into flash, and we don't want to load everything into RAM
    signal_t features_signal;
    features_signal.total_length = sizeof(features) / sizeof(features[0]);
    features_signal.get_data = &raw_feature_get_data;

    // invoke the impulse
    EI_IMPULSE_ERROR res = run_classifier(&features_signal, &result, false /* debug */);
    ei_printf("run_classifier returned: %d\n", res);

    if (res != 0) return;

    // print the predictions
    ei_printf("Predictions ");
    ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
        result.timing.dsp, result.timing.classification, result.timing.anomaly);
    ei_printf(": \n");
    ei_printf("[");
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
        ei_printf("%.5f", result.classification[ix].value);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
        ei_printf(", ");
#else
        if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {
            ei_printf(", ");
        }
#endif
    }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
    ei_printf("%.3f", result.anomaly);
#endif
    ei_printf("]\n");

    // human-readable predictions
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
        ei_printf("    %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
    }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
    ei_printf("    anomaly score: %.3f\n", result.anomaly);
#endif

    delay(1000);
}

void readPH()
{
  for(int i=0;i<10;i++) 
 { 
  buf[i]=analogRead(analogInPin);
  delay(10);
 }
 for(int i=0;i<9;i++)
 {
  for(int j=i+1;j<10;j++)
  {
   if(buf[i]>buf[j])
   {
    temp=buf[i];
    buf[i]=buf[j];
    buf[j]=temp;
   }
  }
 }
 avgValue=0;
 for(int i=2;i<8;i++)
 avgValue+=buf[i];
 pHVol=(float)avgValue*3.3/1024/6;
 phValue = -5.70 * pHVol + 21.34;
 //Serial.print("PH = ");
 //Serial.println(phValue);
}

void readTurbidity()
{
  volt = 0;
    for(int i=0; i<800; i++)
    {
        volt += ((float)analogRead(sensorPin)/1023)*5;
    }
    volt = volt/800;
    volt = round_to_dp(volt,2);
    //Serial.print("Turbidity : ");
    //Serial.println(volt);
}

void readSuhu()
{
  sensors.requestTemperatures(); 
  tempC = sensors.getTempCByIndex(0);
  //Serial.print("Celsius temperature: ");
  //Serial.println(tempC); 
}

float round_to_dp( float in_value, int decimal_place )
{
  float multiplier = powf( 10.0f, decimal_place );
  in_value = roundf( in_value * multiplier ) / multiplier;
  return in_value;
}

Test edge impulse data

fig 2. result dirty water

 

Fig 1. test dirty water

 

Fig 3. report data test

 

Implementation

next step is implementation in my mini Hull Boat, I attach in the bottom of the ship

 

 

 

Sensor Placing

 

Sensor Placing

 

Sensor Placing

1 / 3 • Sensor Placing

 

For the sea actually I have not tested my project, I just simulated with clean water or dirty water. Next if I have the chance I will go overboard to test my project.

Code

IOT Monitoring Marine Pollution

icon IOT-Monitoring-Marine-Pollution-main.zip 11KB Download(1)

The article was first published in hackster, September 27, 2022

cr: https://www.hackster.io/sekolahrobot/portable-vehicle-to-monitoring-marine-pollution-11ec16

author: SekolahRobot

License
All Rights
Reserved
licensBg
0