Programming help for sensors addition


#1

Hello,

I've been working in modifing the OpenRov Code to add an arduino by I2C which would have several sensors from www.atlas-scientific.com connected as we were talking here in this topic http://openrov.com/forum/topics/additional-sensors-to-the-rov . These sensors will measure water temperature, pH of the water, water conductivity, ORP and dissolved oxygen.

My idea is to:

  • Modify the envdata class in device.h to include this data I want to measure, for example static float ACID.
  • Inicialize this new data in device.cpp. To do that I will include a line similar to the existing ones, such as float envdata::ACID = 0
  • Modify the OutputSharedData function in device.cpp in order to include the viewing of these new variables, as well as the existing ones

Serial.print(F("acidity:"));

Serial.print(envdata::ACID);
Serial.print(';');

I think that would be enough to have the new data displayed in the monitor, for now with value = 0.

The final step would be to create our new I2Cdevice to receive the date from the slave arduino. I think the more economical way is to define a struct with the data and send it right away. As the only thing this arduino would do is to send these data I think I would only have to use the RequestEvent function.

If you think these steps wouldn't work, could you please tell me why and how to improve this process?

I would like you to tell me how to accede the arduino code to include these modifications and also how to create the I2Cdevice.

Regards!

Javi


#2

Hi Javi,

Glad your interested in adding to the community! Some things you may want to consider. While you can definitely use the existing classes as models, you probably should add the code to control your device to a separate module so that you can continue to get new updates without having conflicts. The plugin model will be extended to the Arduino code shortly.

The goal of the envdata class was to make data that would be useful by other devices sharable between modules. Water temperature for instance is needed by many other devices in order to do there measurements. In this case, you should be able to simply update the water temperature that is already in the class.

For other types of data, the easiest way is to simply Serial.print the resulting data in our own device_loop() function. Notice how the auto pilot code automatically outputs data that is unique to its function: https://github.com/OpenROV/openrov-software-arduino/blob/master/OpenROV/Pilot.cpp#L165-L167

If you do have data that you feel will be needed by other modules on the Arduino, I would say go ahead and make a case for it and submit the pull request as getting it integrated in to the rest of the code prevents future conflicts.

As far as the I2C goes, you can see several examples in the code today. In the case of the Pressure Sensor (https://github.com/OpenROV/openrov-software-arduino/blob/master/OpenROV/MS5803_14BA.cpp), Walt simply walked through the data sheet for the sensor and directly wrote to the I2c using the wire library. Other sensors, such as the MPU9150 incorporate a third party library that abstracts the I2c device access a bit.

Hope that helps.

-Brian


#3

Thank you a lot Brian.

I know that it should be basic but I don't know how to accede to the code of the arduino to modificate it. I've always work with standar arduinos which you can connect to the comuter by USB.

Regards!

Javi


#4

Hello Brian,

I've been working on this project and I promise you I will soon show you all the codes so that you can use them if you want.

I would like to know a couple of things before. If I want to send the data like it is done in the auto pilot code how would I show this data in the computer screen. Have you got any tutorial of how to do this?

The other thing I would like to know is what is he input voltage of the depth sensor... 3V or 5V?

Thanks for the help!

Regards!


#5

According to schematic the depth sensor is connected to 3.3 volt.


#6

I want to conect an arduino to the I2C bus but arduino must be connected at least on 7V. How do you think I should connect this arduino?


#7

Hello Brian,

I let you here the codes I've been developing.

In the dataadquisition of the arduino there would be this code:

#include <AltSoftSerial.h> //Include the software serial library
#include <Wire.h>

const byte i2c_address=0x77;
AltSoftSerial altSerial; //Name the software serial library altSerial (this cannot be omitted)

int s0 = 7; //Arduino pin 7 to control pin S0
int s1 = 6; //Arduino pin 6 to control pin S1

char sensordata[30]; //A 30 byte character array to hold incoming data from the sensors
byte sensor_bytes_received=0; //We need to know how many characters bytes have been received

struct data
{
struct {
float ec;
float tds;
float sal;
float sg;
}
conductivity;
float pH;
float DO;
float ORP;
float temperature;
};

const int data_size=sizeof(data);

const int waiting_time = 1000;

data data_from_sensors = {
{
0, 0, 0, 0 }
,
0,
0,
0,
0
};

void setup() {
pinMode(s1, OUTPUT); //Set the digital pin as output.
pinMode(s0, OUTPUT); //Set the digital pin as output.
pinMode(2, OUTPUT); //Set pin 2 as an output
Serial.begin(38400); //Set the hardware serial port to 38400
altSerial.begin(38400); //Set the soft serial port to 38400
Wire.begin(i2c_address);
Wire.onRequest(requestEvent);
}





void loop(){
data_from_sensors.temperature = read_temp();
open_channel(0);
Serial.print("Conductivity==>");
altSerial.print("R\r");
leeBuffer();
const char *delimitador=",";
data_from_sensors.conductivity.ec=atof(strtok(sensordata,delimitador));
data_from_sensors.conductivity.tds=atof(strtok(NULL,delimitador));
data_from_sensors.conductivity.sal=atof(strtok(NULL,delimitador));
data_from_sensors.conductivity.sg=atof(strtok(NULL,delimitador));

open_channel(1);
Serial.print("pH==>");
altSerial.print("R\r");
leeBuffer();
data_from_sensors.pH=atof(sensordata);

open_channel(2);
Serial.print("DO==>");
altSerial.print("R\r");
leeBuffer();
data_from_sensors.DO=atof(sensordata);

open_channel(3);
Serial.print("ORP==>");
altSerial.print("R\r");
leeBuffer();
data_from_sensors.ORP=atof(sensordata);

Serial.println();
Serial.println(" DATA IN STRUCTURE ");
Serial.println("-------------------");
Serial.print("Conductividad==> EC: ");
Serial.print(data_from_sensors.conductivity.ec);
Serial.print(", TDS: ");
Serial.print(data_from_sensors.conductivity.tds);
Serial.print(", SAL: ");
Serial.print(data_from_sensors.conductivity.sal);
Serial.print(", SG: ");
Serial.println(data_from_sensors.conductivity.sg);

Serial.print("pH==> ");
Serial.println(data_from_sensors.pH);
Serial.print("DO==> ");
Serial.println(data_from_sensors.DO);
Serial.print("ORP==> ");
Serial.println(data_from_sensors.ORP);

// resto de datos de la estructura
Serial.print("Temperatura==> ");
Serial.println(data_from_sensors.temperature);

Serial.println("-------------------");
Serial.println(" DATA IN STRUCTURE END ");
Serial.println();
delay(5000);
}

void leeBuffer(){
delay(waiting_time);
if(altSerial.available() > 0){ //If data has been transmitted from an Atlas Scientific device
sensor_bytes_received=altSerial.readBytesUntil(13,sensordata,30); //we read the data sent from the Atlas Scientific device until we see a <CR>. We also count how many character have been received
sensordata[sensor_bytes_received]=0; //we add a 0 to the spot in the array just after the last character we received. This will stop us from transmitting incorrect data that may have been left in the buffer
Serial.println(sensordata);
}
}

void open_channel(int channel){ //This function controls what UART port is opened.

if (channel & 1){
digitalWrite(s0, HIGH);
}
else {
digitalWrite(s0,LOW);
}
if (channel & 2){
digitalWrite(s1, HIGH);
}
else {
digitalWrite(s1,LOW);
}
delay(100);
int bytesResiduo=altSerial.available();
if(bytesResiduo > 0){
sensor_bytes_received=altSerial.readBytes(sensordata, bytesResiduo);
sensordata[bytesResiduo]=0;
Serial.print("ATENCION: DATOS NO LEIDOS: ");
Serial.println(sensordata);
}
}

float read_temp(void){ //the read temperature function
float v_out; //voltage output from temp sensor
float temp; //the final temperature is stored here
digitalWrite(A0, LOW); //set pull-up on analog pin
digitalWrite(2, HIGH); //set pin 2 high, this will turn on temp sensor
delay(2); //wait 2 ms for temp to stabilize
v_out = analogRead(0); //read the input pin
digitalWrite(2, LOW); //set pin 2 low, this will turn off temp sensor
v_out*=.0048; //convert ADC points to volts (we are using .0048 because this device is running at 5 volts)
v_out*=1000; //convert volts to millivolts
temp= 0.0512 * v_out -20.5128; //the equation from millivolts to temperature
return temp; //send back the temp
}

void requestEvent(){
byte *pDatos= (byte *) &data_from_sensors;
Wire.write(pDatos, data_size);
}

Arduslave.h

#ifndef __ArduSlave_H_
#define __ArduSlave_H_
#include <Arduino.h>
#include "Device.h"

struct data
{
struct {
float ec;
float tds;
float sal;
float sg;
}
conductivity;
float pH;
float DO;
float ORP;
float temperature;
};
const int data_size=sizeof(data);

const unsigned arduslave_timeout=100;

class ArduSlave : public Device {
public:
ArduSlave():Device(){};
void device_setup();
void device_loop(Command cmd);
};
#endif

arduslave.cpp:

#include "AConfig.h"
#if(HAS_ARDUSLAVE)

#include "ArduSlave.h"
// #include "Settings.h"
//#include "Timer.h"
#include <Wire.h>

/*
Sketch to read a MS5803-14BA pressure sensor, written from scratch.
Will output data to the serial console.

Written by Walt Holm
Initial revision 10 Oct 2013
Rev 1 12 Oct 2013 -- Implements 2nd order temperature compensation
*/



const int DevAddress = ARDUSLAVE_I2CADDRESS; // 7-bit I2C address of the MS5803

void ArduSlave::device_setup(){
//Settings::capability_bitarray |= (1 << DEAPTH_CAPABLE);

Serial.println("ArduSlave setup.");
Wire.begin();
delay(10);
}

void ArduSlave::device_loop(Command command){
Wire.requestFrom(DevAddress, 32);
data data_from_arduslave;

unsigned int millis_start = millis();
byte *pBdata = (byte *) &data_from_arduslave;
for (int i=0; i<data_size; i++){
if (Wire.available()){
pBdata[i]=Wire.read();
}
else {
if (((unsigned int)millis() - millis_start) > arduslave_timeout) {
Serial.println("log:Failed to read ArduSlave from I2C");
return;
}
}
}
Serial.println();
Serial.println(" DATA IN ARDUSLAVE ");
Serial.println();
Serial.print("Conductividad==> EC: ");
Serial.print(data_from_arduslave.conductivity.ec);
Serial.print(", TDS: ");
Serial.print(data_from_arduslave.conductivity.tds);
Serial.print(", SAL: ");
Serial.print(data_from_arduslave.conductivity.sal);
Serial.print(", SG: ");
Serial.println(data_from_arduslave.conductivity.sg);

Serial.print("pH==> ");
Serial.println(data_from_arduslave.pH);
Serial.print("DO==> ");
Serial.println(data_from_arduslave.DO);
Serial.print("ORP==> ");
Serial.println(data_from_arduslave.ORP);

// resto de datos de la estructura
Serial.print("Temperatura==> ");
Serial.println(data_from_arduslave.temperature);

Serial.println();
Serial.println(" DATA IN ARDUSLAVE END ");
Serial.println();
}
#endif

Now I need to modify the javascript code to see this data, isn't is?


#8

Hey Javier,

Did you figure out a solution?


#9

No, I haven't yet. I don't know if I can feed the slave arduino independently, and connect it to the I2C bus....

Are there pull up resistences in the I2C bus on the openrov?


#10

I've having problems with the code so I wanted to show it to you.

293-cpp1.jpg (202 KB) 294-cpp2.jpg (173 KB) 295-compilando.jpg (90.7 KB)

#11

Hey Javeir,

Do you have this in a git repo I can pull somewhere?


#12

No I dont have it still uploaded to github because I wanted to check if it works before.