Atlas Scientific Ardiuno to Particle code issues

Hey Ali,

It seems as if the Tentacle is still in its packaging foam. If so, you must remove it immediately. The foam is conductive - probably causing all kinds of issues. No Magic Smoke I hope!

Solid blue means I2C. So the mode switch worked for you. By repeating the same procedure, you can toggle the UART/I2C mode back and forth. The blinking to Cyan only happens when a reading is taken. In serial mode, the standard setting is “continuous mode = on”. That’s why it blinks every second. In I2C mode however, there is no continuous mode. It’s not possible for an I2C slave to “send” data without being asked by the I2C master first.

Also, in case you have an Arduino, you can plug it in there (remove all cables first) and load the setup sketch. It will do auto-detection of the plugged circuits etc. That’s an easy and interactive way to get to know your EZOs. Once configured, switch back to the Photon.

Patrick

I do not have an Arduino. There was no Smoke. How do i check if this is working now? Because im not receiving any data from it. Gavin’s test sketch reads every 1.8 secs and all i see is No data on the serial monitor.

The EZOs are on, so the get power, everything alright on that end. If you don’t see the cyan blinking every 1.8 seconds, your communications are not working. SCL/SDA seem wired correctly… but can you double check you’re using the right pin for IOREF? There’s also a non-labeled NC pin next to IOREF - can’t make it out on the photo.

@Gavin and the rest of you here.

I dig your DankLettuce website too, except the dig on elitist growers in certain areas :cry:

If you feel like adventuring with us, www.commongarden.org is a dashboard built with meteor for hardware to log and control sensors and hardware for Hydroponic and Aeroponic use.

While not specifically catering to particle devices, after finding this open source project, I decided to buckle down on the javascript skillset so I can contribute, or at least attempt to know what I am doing eventually, and maybe in the process get particle devices as a first-tier choice along with the Tessel 2 that the developers of project seem to love.

I am facing an issue with the tentacle mini. The error is completely random. Works flwaless at times and sometimes shows up in a few minutes of use. The Ezo’s stop taking any readings and everything connected to i2c fails. A reset on the photon does not make it work. I either need to remove power or press reset on the tentacle mini to get everything working again.

Hello Ali,

have you tried debugging when that error condition happens? What’s the LED state of the EZO’s when this happens? Can you measure voltage on the Tentacle 5V pin and the isolated VCC pins (EZO pin connector, lower left)?
What other I2C devices do you have attached?
Do you have the Tentacle Reset pin wired to your photon? Because… the reset-button does not do anything without being connected to the actual microcontroller reset. This in turn makes it sound weird that the photon reset does not help, while the tentacle reset does. Are you sure about that?

The LED’s are in solid blue state. I have not measured voltage but i will next time the error happens. I have a 16 channel relay board and a pressure sesnor breakout board from CE attached. I did not attach the rst pin to the photon but i will do that now.
RESET to RST on photon.

Issue happened again! The reset is connected to the photon but it doesn’t reset the board. I have to press reset on the mini to get the i2c bus to respond. Or do a power cycle. Voltage is reading 5v at 5v and 3.3v on ioref. Wire.endtransmission() returns 1.

@ScruffR @Whitebox_Labs
i was having issues with the sensors causing the i2c bus to hang. The code above posted by Gavin was broken into send and receive so that i did not have to call delay. I am using a timer between send and receive. My code looks like below

void requestFromWaterSensors(String command, int i2cAddress) {
    Wire.beginTransmission(i2cAddress); //call the circuit by its ID number.
    Wire.write(command); //transmit the command that was sent through the serial port.
    int wireStatus = Wire.endTransmission(); //end the I2C data transmission. 
    if (wireStatus != 0) {
        i2cSuccess = false;
        //debug(String::format("wireReq: %d", wireStatus));
        //Wire.reset();
    } else if (wireStatus == 0) {
        i2cSuccess = true;
    }
}

and for the receive a timer is used immediately after requestfromWaterSensors() is called that has receiveFromWaterSensors() as its callback function.

void receiveFromWaterSensors(String command, int i2cAddress, char* sensorData) {
    if (i2cSuccess) {
        Wire.requestFrom(i2cAddress, 48, 1); //call the circuit and request 48 bytes (this is more then we need).
        code = Wire.read(); //the first byte is the response code, we read this separately.

        while (Wire.available()) { //are there bytes to receive.
            in_char = Wire.read(); //receive a byte.
            sensorData[i] = in_char; //load this byte into our array.
            i += 1; //incur the counter for the array element.
            if (in_char == 0) { //if we see that we have been sent a null command.
                i = 0; //reset the counter i to 0.
                int wireStatus = Wire.endTransmission(); //end the I2C data transmission.
                if (wireStatus != 0) {
                    debug(String::format("wireRecv: %d", wireStatus));
                    //Wire.reset();
                } else if (wireStatus == 0) {
                    //i2cSuccess = true;
                }
                break; //exit the while loop.
            }
        }

        switch (code) { //switch case based on what the response code is.
            case 1: //decimal 1.
                Serial.println("Success"); //means the command was successful.
                //debug("Success");
                break; //exits the switch case.

            case 2: //decimal 2.
                Serial.println("Failed"); //means the command has failed.
                //debug("Failed");
                break; //exits the switch case.

            case 254: //decimal 254.
                Serial.println("Pending"); //means the command has not yet been finished calculating.
                //debug("Pending");
                break; //exits the switch case.

            case 255: //decimal 255.
                //Serial.println("No Data"); //means there is no further data to send.
                //debug("No Data");
                break; //exits the switch case.
        }

        if (i2cAddress == EC_ADDRESS) {
            convertECstring();
        } else if (i2cAddress == PH_ADDRESS) {
            pH = sensorData;
        }
        //debug(sensorData);
    }
}

by this i can use the same code for reading from multiple sensors and it works well for the most part but i have random errors. Sometime the system runs for 4-5 days and sometimes a few hours. The error originates in the receive function where Wire.endTransmission() returns 1. I can call Wire.reset() and fix the issue but i am unsure of whether that would be the best fix for the issue.

Is there another way to accomplish receiving from the sensors without using delay() or is there anything wrong i am doing with the code?

@Ali Have you tried testing some of the code from above to see if it is a firmware vs. hardware issue? It would be good to confirm that the setup is working with code that is known to run successfully by others.

I did not run it for more than a few hours with gavin’s test code that was above. I was running it in the actual product with all the other components. I have removed the board from the product and set up a test rig that will run this weekend to see what happens. The above code seems to be for serial and i am using i2c for communication.

Hey @Ali Ali,

I think it is the stamp, I had the same issue. What happens if you have the old stamp, there is a new atlas stamp out now. If the old stamp gets turned off at 900ms it will go into default mode and the only way to reset it by the manual method.

I send an email to Atlas scientific and they confirmed it was a hardware issue.

Though your issue maybe something else, but yeah I had the issue where randomly my stamp would go from i2c to default.

Cheers,

Erkele

@Whitebox_Labs any luck throwing together some examples for Photon? I have been reading a pH probe from Atlas but just got a tentacle mini and ORP probe. I also got a shield shield to try to adapt the photon to the arduino shield footprint. Has anyone had any luck with that?

Unfortunately the Tentacle Mini and Particle Shield Shield don’t work together.

Hello @keenest and @mrOmatic

I have atlast scientific working on the particle, as well the sheild sheild does work with particle, you just need to connect in half the pins. I have it working.

Kind regards,

Erkele

1 Like

Can you post a picture of something showing how you have it working?

I’m interested in using this in the future for water purification project.

I’d call that a workaround. But happy you got it working.

Please send a pic and/or diagram! I would love to be able to use the shield shield as it makes for a very neat and compact finished product.

I'm confused here. Why won't the Tentacle Mini and Shield Shield work? The pin mapping seems to be exactly how I have the photon wired to the tentacle mini. What am I missing?

Thank you @Gavin for the reference code. I was able to modify what you had to work with just the pH meter on a photon.

I was able to switch from uART to I2C manually but I forgot to move the connections from Tx Rx to the SCL and SDA pins on the Photon. This was causing me to return nulls. Once I discovered my embarrassing mistake, I moved the Rx connection on the Photon to D1 and Tx to D0. Now it works!

//**THIS CODE WILL WORK ON ANY ARDUINO**
//This code has intentionally has been written to be overly lengthy and includes unnecessary steps.
//Many parts of this code can be truncated. This code was written to be easy to understand.
//Code efficiency was not considered. Modify this code as you see fit.
//This code will output data to the Arduino serial monitor. Type commands into the Arduino serial monitor to control the EZO EC Circuit in I2C mode.


#include <Wire.h>                //enable I2C.
#define address 99              //default I2C ID number for EZO pH Circuit.



char computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte received_from_computer = 0; //we need to know how many characters have been received.
bool serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char pH_data[24];                //we make a 24 byte character array to hold incoming data from the pH circuit.
byte in_char = 0;                //used as a 1 byte buffer to store in bound bytes from the EC Circuit.
byte i = 0;                      //counter used for ec_data array.
int delay_time = 1400;           //used to change the delay needed depending on the command sent to the EZO Class pH Circuit.

char *pH;                        //char pointer used in string parsing.


float pH_float;                  //float var used to hold the float value of the pH.


void setup()                     //hardware initialization.
{
  Serial.begin(9600);            //enable serial port.
  Wire.begin();                  //enable I2C port.
}


void serialEvent() {           //this interrupt will trigger when the data coming from the serial monitor(pc/mac/other) is received.
  received_from_computer = Serial.readBytesUntil(13, computerdata, 20); //we read the data sent from the serial monitor(pc/mac/other) until we see a <CR>. We also count how many characters have been received.
  computerdata[received_from_computer] = 0; //stop the buffer from transmitting leftovers or garbage.
  serial_event = true;           //set the serial event flag.
}

void loop() {                   //the main loop will take a reading every 5 seconds.

//    computerdata[0] = 'r'; //Take a reading
    computerdata[0] = 'R';
    delay_time=1800; // Need to set the delay to 1.8 seconds when taking a reading

    Wire.beginTransmission(address);            //call the circuit by its ID number.
    Wire.write(computerdata);                   //transmit the command that was sent through the serial port.
    Wire.endTransmission();                     //end the I2C data transmission.

    delay(delay_time);                        //wait the correct amount of time for the circuit to complete its instruction.

    Wire.requestFrom(address, 24, 1);          //call the circuit and request 24 bytes (this is more then we need).
    code = Wire.read();                        //the first byte is the response code, we read this separately.
    
    while (Wire.available()) {                  //are there bytes to receive.
      in_char = Wire.read();                    //receive a byte.
      pH_data[i] = in_char;                     //load this byte into our array.
      i += 1;                                   //incur the counter for the array element.
      if (in_char == 0) {                       //if we see that we have been sent a null command.
        i = 0;                                  //reset the counter i to 0.
        Wire.endTransmission();                 //end the I2C data transmission.
        break;                                  //exit the while loop.
      }
    }
       
    switch (code) {                           //switch case based on what the response code is.
      case 1:                                 //decimal 1.
        Serial.println("Success");            //means the command was successful.
        break;                                //exits the switch case.

      case 2:                                 //decimal 2.
        Serial.println("Failed");             //means the command has failed.
        break;                                //exits the switch case.

      case 254:                               //decimal 254.
        Serial.println("Pending");            //means the command has not yet been finished calculating.
        break;                                //exits the switch case.

      case 255:                               //decimal 255.
        Serial.println("No Data");            //means there is no further data to send.
        break;                                //exits the switch case.
    }
  
    Serial.println(pH_data);                  //print the data.
    serial_event = false;                      //reset the serial event flag.

    if(computerdata[0]=='R') string_pars(); //Call the Strign_Pars() function to break up the comma separated ec_data string into its individual parts.
    
    delay(5000-delay_time); //this will pause until 5 seconds have elapsed from previous reading
  }

void string_pars() {                  //this function will break up the CSV string into its 4 individual parts. EC|TDS|SAL|SG.
                                      //this is done using the C command “strtok”.

  pH = strtok(pH_data, ",");          //let's pars the string at each comma.

//  Serial.print("pH:");                //we now print each value we parsed separately.
//  Serial.println(pH);                 //this is the pH value.
  Spark.publish("pH", String(pH));
  

  //uncomment this section if you want to take the values and convert them into floating point number.
  /*
  ec_float=atof(ec);
  tds_float=atof(tds);
  sal_float=atof(sal);
  sg_float=atof(sg);
  */
}
1 Like