Aquaponics Project HELP!

Hello to everybody:

I have an Issue, I am trying to connect a arduino with an Ethernet shield to the Thingspeak platform to read the values of a pH and DO atlas sensors connected to the tentacle shield mini, they are in I2C mode. The issue is that I can see the value of the data through the serial port but I can´t see the information in the Thingspeak server, I am using the Thingspeak library and the Thingspeak.writefield.

This is so far my code:

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>                     // enable I2C.
#include <ThingSpeak.h>

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

byte code = 0;                        // used to hold the I2C response code.
byte in_char = 0;                     // used as a 1 byte buffer to store in bound bytes from the I2C Circuit.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
EthernetServer server(80);
EthernetClient client;
IPAddress ip(10,24,178,100);

#define TOTAL_CIRCUITS 2              // <-- CHANGE THIS | set how many I2C circuits are attached to the Tentacle shield(s): 1-8

int channel_ids[] = {97, 99};
// A list of I2C ids that you set your circuits to.
// This array should have 1-8 elements (1-8 circuits connected)

char *channel_names[] = {"DO", "PH"}; 
// A list of channel names (must be the same order as in channel_ids[]) 
// it's used to give a name to each sensor ID. This array should have 1-8 elements (1-8 circuits connected).

// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";
unsigned long myChannelNumber = 365215;
const char * myWriteAPIKey = "JHWZ45JGLKZA6ICM";


void setup() {                      // startup function
 Serial.begin(9600); // Set the hardware serial port.
 SPI.begin();
 Wire.begin();         // enable I2C port.
 Ethernet.begin(mac, ip);
 ThingSpeak.begin(client);
}



void loop() {

 for (int channel = 0; channel < TOTAL_CIRCUITS; channel++) {       // loop through all the sensors
   Wire.beginTransmission(channel_ids[channel]);     // call the circuit by its ID number.
   Wire.write('r');                          // request a reading by sending 'r'
   Wire.endTransmission();                         // end the I2C data transmission.
   
   delay(1000);  // AS circuits need a 1 second before the reading is ready

   sensor_bytes_received = 0;                        // reset data counter
   memset(sensordata, 0, sizeof(sensordata));        // clear sensordata array;

   Wire.requestFrom(channel_ids[channel], 48, 1);    // call the circuit and request 48 bytes (this is more then we need).
   code = Wire.read();

   while (Wire.available()) {          // are there bytes to receive?
     in_char = Wire.read();            // receive a byte.

     if (in_char == 0) {               // null character indicates end of command
       Wire.endTransmission();         // end the I2C data transmission.
       break;                          // exit the while loop, we're done here
     }
     else {
       sensordata[sensor_bytes_received] = in_char;      // append this byte to the sensor data array.
       sensor_bytes_received++;
     }
   }
   Serial.print(channel_names[channel]);   // print channel name
   Serial.print(':');

   switch (code) {                       // switch case based on what the response code is.
     case 1:                             // decimal 1  means the command was successful.
       Serial.println(sensordata);       // print the actual reading
       break;                              // exits the switch case.

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

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

     case 255:                           // decimal 255 means there is no further data to send.
       Serial.println("no data");          // print the error
       break;                              // exits the switch case.
   }
   ThingSpeak.writeField(myChannelNumber, channel, sensordata, myWriteAPIKey);
   delay(20000); // ThingSpeak will only accept updates every 15 seconds.
 }
}

Thanks for everything and let´s see if someone can bring a light to the problem.

Julio Pérez

Please read the "How to use this forum" post and edit your post so that the code is posted properly.

       Wire.endTransmission();         // end the I2C data transmission.

I don't see the beginTransmission() statement that this closes. It's pointless to close something that isn't open.

   Wire.requestFrom(channel_ids[channel], 48, 1);    // call the circuit and request 48 bytes (this is more then we need).

Why are you asking for 48, then? The array where you write the up-to-48 bytes can only hold 30. You don't check that there is room before writing to the array, so it is possible that you are trashing memory you don't own. That is NOT "a good thing".

   ThingSpeak.writeField(myChannelNumber, channel, sensordata, myWriteAPIKey);

Does this function really take an array as the 3rd argument? How is it supposed to know how much data is in the array?

Hi:

The beginning of the transmision is ate the beginning of the if.

About the 48 yeah I think I will change that to 30

Regarding the third question I think that it handles the arrays because it return me no error when compiling

return me no error when compiling

That just means it's legal, not that it will work. You should consult the documentation to answer that question.

Kurogarasu: Regarding the third question I think that it handles the arrays because it return me no error when compiling

Talk about wishful thinking.

Looking at the code on GitHub, it will take a char *. But, better make sure the array is null terminated.

The beginning of the transmision is ate the beginning of the if.

Which if? I only see ONE if statement in your program, where you may, or may not, call Wire.endTransmission(). There is a call to Wire.beginTransmission() at the top of the for loop, but that is followed, two lines later, by a call to Wire.endTransmission().

There are no other calls to Wire.beginTransmission(), so it is wrong to have that call to Wire.endTransmission().