Ethernet - Loop, For where to put it?

I need to Loop trough sensors to get the Temperature reading and then to send over the network, all working fine except the FOR procedure, I don't know where to put it properly.

void loop () {
  sensors.requestTemperatures();
  ether.packetLoop(ether.packetReceive());
  
  if (millis() > timer) {
   memset(xUrl, 0, sizeof(xUrl));
   
   timer = millis() + 5000;
   Serial.println();

   for (int iCount = 0; iCount < iNumOfSens; iCount++) {
    memset(sTempC, 0, sizeof(sTempC));
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);
    sprintf(xUrl, "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=%s", iCount, sTempC);
    
    ether.browseUrl(PSTR(""), xUrl, sServer, brw_cb);
    
    Serial.println(xUrl);
   }
    
  }
  
}
    memset(sTempC, 0, sizeof(sTempC));

Not necessary. The dtostrf() function properly NULL terminates the array.

The for loop is fine where it is. What it does is not. You need to loop through the sensors, getting the temperature of each, and converting to a string. You append that to a larger string, in the for loop. AFTER the loop, send the data.

PaulS:

    memset(sTempC, 0, sizeof(sTempC));

Not necessary. The dtostrf() function properly NULL terminates the array.

The for loop is fine where it is. What it does is not. You need to loop through the sensors, getting the temperature of each, and converting to a string. You append that to a larger string, in the for loop. AFTER the loop, send the data.

Thanks for finding that unnecessary piece of line in my code.

I read what you proposed to me, but unfortunately I'm not a C guru, I wish there are some VB related IDE for Arduino! :frowning:

Can you please help me to fix my code PaulS?!

Bottom is some server test code that displays the value of the arduino analog pins in a web page. Below is a link to a how-to for slicker looking web pages.

// zoomkat's meta refresh data frame test page 5/25/13
// use http://192.168.1.102:84 in your brouser for main page
// http://192.168.1.102:84/data static data page
// http://192.168.1.102:84/datastart meta refresh data page
// for use with W5100 based ethernet shields
// set the refresh rate to 0 for fastest update
// use STOP for single data updates

#include <SPI.h>
#include <Ethernet.h>

const int analogInPin0 = A0;
const int analogInPin1 = A1;
const int analogInPin2 = A2;
const int analogInPin3 = A3;
const int analogInPin4 = A4;
const int analogInPin5 = A5;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
unsigned long int x=0; //set refresh counter to 0
String readString; 

//////////////////////

void setup(){
  Serial.begin(9600);
    // disable SD SPI if memory card in the uSD slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  Serial.println("meta refresh data frame test 5/25/13"); // so I can keep track of what is loaded
}

void loop(){
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
         if (readString.length() < 100) {
          readString += c; 
         } 
        //check if HTTP request has ended
        if (c == '\n') {

          //check get atring received
          Serial.println(readString);

          //output HTML data header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          //generate data page
          if(readString.indexOf("data") >0) {  //checks for "data" page
            x=x+1; //page upload counter
            client.print("<HTML><HEAD>");
            //meta-refresh page every 1 seconds if "datastart" page
            if(readString.indexOf("datastart") >0) client.print("<meta http-equiv='refresh' content='1'>"); 
            //meta-refresh 0 for fast data
            if(readString.indexOf("datafast") >0) client.print("<meta http-equiv='refresh' content='0'>"); 
            client.print("<title>Zoomkat's meta-refresh test</title></head><BODY>
");
            client.print("page refresh number: ");
            client.print(x); //current refresh count
            client.print("

");
            
              //output the value of each analog input pin
            client.print("analog input0 is: ");
            client.print(analogRead(analogInPin0));
            
            client.print("
analog input1 is: ");
            client.print(analogRead(analogInPin1));
                        
            client.print("
analog input2 is: ");
            client.print(analogRead(analogInPin2));
            
            client.print("
analog input3 is: ");
            client.print(analogRead(analogInPin3));
                                    
            client.print("
analog input4 is: ");
            client.print(analogRead(analogInPin4));
            
            client.print("
analog input5 is: ");
            client.print(analogRead(analogInPin5));
            client.println("
</BODY></HTML>");
           }
          //generate main page with iframe
          else
          {
            client.print("<HTML><HEAD><TITLE>Zoomkat's frame refresh test</TITLE></HEAD>");
            client.print("Zoomkat's Arduino frame meta refresh test 5/25/13");
            client.print("

Arduino analog input data frame:
");
            client.print("&nbsp;&nbsp;<a href='http://192.168.1.102:84/datastart' target='DataBox' title=''yy''>META-REFRESH</a>");
            client.print("&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://192.168.1.102:84/data' target='DataBox' title=''xx''>SINGLE-STOP</a>");
            client.print("&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://192.168.1.102:84/datafast' target='DataBox' title=''zz''>FAST-DATA</a>
");
            client.print("<iframe src='http://192.168.1.102:84/data' width='350' height='250' name='DataBox'>");
            client.print("</iframe>
</HTML>");
          }
          delay(1);
          //stopping client
          client.stop();
          //clearing string for next read
          readString="";
        }
      }
    }
  }
}

zoomkat:
Bottom is some server test code that displays the value of the arduino analog pins in a web page. Below is a link to a how-to for slicker looking web pages.

Arduino AJAX Web Server for Reading a Switch Automatically.

// zoomkat's meta refresh data frame test page 5/25/13

// use http://192.168.1.102:84 in your brouser for main page
// http://192.168.1.102:84/data static data page
// http://192.168.1.102:84/datastart meta refresh data page
// for use with W5100 based ethernet shields
// set the refresh rate to 0 for fastest update
// use STOP for single data updates

#include <SPI.h>
#include <Ethernet.h>

const int analogInPin0 = A0;
const int analogInPin1 = A1;
const int analogInPin2 = A2;
const int analogInPin3 = A3;
const int analogInPin4 = A4;
const int analogInPin5 = A5;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
unsigned long int x=0; //set refresh counter to 0
String readString;

//////////////////////

void setup(){
  Serial.begin(9600);
    // disable SD SPI if memory card in the uSD slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  Serial.println("meta refresh data frame test 5/25/13"); // so I can keep track of what is loaded
}

void loop(){
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (readString.length() < 100) {
          readString += c;
        }
        //check if HTTP request has ended
        if (c == '\n') {

//check get atring received
          Serial.println(readString);

//output HTML data header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

//generate data page
          if(readString.indexOf("data") >0) {  //checks for "data" page
            x=x+1; //page upload counter
            client.print("");
            //meta-refresh page every 1 seconds if "datastart" page
            if(readString.indexOf("datastart") >0) client.print("");
            //meta-refresh 0 for fast data
            if(readString.indexOf("datafast") >0) client.print("");
            client.print("Zoomkat's meta-refresh test
");
            client.print("page refresh number: ");
            client.print(x); //current refresh count
            client.print("

");
           
              //output the value of each analog input pin
            client.print("analog input0 is: ");
            client.print(analogRead(analogInPin0));
           
            client.print("
analog input1 is: ");
            client.print(analogRead(analogInPin1));
                       
            client.print("
analog input2 is: ");
            client.print(analogRead(analogInPin2));
           
            client.print("
analog input3 is: ");
            client.print(analogRead(analogInPin3));
                                   
            client.print("
analog input4 is: ");
            client.print(analogRead(analogInPin4));
           
            client.print("
analog input5 is: ");
            client.print(analogRead(analogInPin5));
            client.println("

");           }           //generate main page with iframe           else           {             client.print("Zoomkat's frame refresh test");             client.print("Zoomkat's Arduino frame meta refresh test 5/25/13");             client.print("

Arduino analog input data frame:
");
            client.print("  <a href='http://192.168.1.102:84/datastart' target='DataBox' title=''yy''>META-REFRESH");
            client.print("    <a href='http://192.168.1.102:84/data' target='DataBox' title=''xx''>SINGLE-STOP");
            client.print("    <a href='http://192.168.1.102:84/datafast' target='DataBox' title=''zz''>FAST-DATA
");
            client.print("

");           }           delay(1);           //stopping client           client.stop();           //clearing string for next read           readString="";         }       }     }   } } > ```

Thanks zoomkat, but there is no For loop either it not using the ENC28J60 Ethernet Library! :frowning:

Here is your for loop:

  for (int iCount = 0; iCount < iNumOfSens; iCount++) {
    memset(sTempC, 0, sizeof(sTempC));
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);
    sprintf(xUrl, "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=%s", iCount, sTempC);
    
    ether.browseUrl(PSTR(""), xUrl, sServer, brw_cb);
    
    Serial.println(xUrl);
   }

It gets a temperature, converts it to a string, ans sends it to the server.

Here is your code without the "and sends it to the server part".

  for (int iCount = 0; iCount < iNumOfSens; iCount++) {
    memset(sTempC, 0, sizeof(sTempC));
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);
    sprintf(xUrl, "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=%s", iCount, sTempC);
    
    Serial.println(xUrl);
   }

See the difference?

Here is the code that gets all the sensor data, and sends it to the server after getting it all:

  for (int iCount = 0; iCount < iNumOfSens; iCount++) {
    memset(sTempC, 0, sizeof(sTempC));
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);
    sprintf(xUrl, "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=%s", iCount, sTempC);
    
      Serial.println(xUrl);
   }
    ether.browseUrl(PSTR(""), xUrl, sServer, brw_cb);

Now, the problem with the last code is that it will send only the last reading.

The interesting part of the URL is "&svalue=%s" where the temperature is sent.

Now, suppose that you defined an array that contained "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&" that had room for iNumOfSens "svalue=%s" blocks of data. Could you define such an array?

Keep in mind that "&svalue=%s" needs to have a numeric value, to distinguish the 1st value from the 2nd, the 3rd, etc.

Could you create a sprintf() statement that output "&svalue%d=%d" with a value for the ist parameter (the loop index) and the second value (the temperature from the ith sensor)?

Appending the nth string to the base string is done using strcat(). Do you know how to call that function?

PaulS:
Now, the problem with the last code is that it will send only the last reading.

The interesting part of the URL is "&svalue=%s" where the temperature is sent.

Now, suppose that you defined an array that contained "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&" that had room for iNumOfSens "svalue=%s" blocks of data. Could you define such an array?

Keep in mind that "&svalue=%s" needs to have a numeric value, to distinguish the 1st value from the 2nd, the 3rd, etc.

Could you create a sprintf() statement that output "&svalue%d=%d" with a value for the ist parameter (the loop index) and the second value (the temperature from the ith sensor)?

Appending the nth string to the base string is done using strcat(). Do you know how to call that function?

Ohh yeah, now you are getting my project PaulS! :wink:

Here is what I really want...

I have now 3x DS18B20 sensors attached (but it will be more, less, randomly added/removed) 1Wire on Parasite mode.

So, I collect the number of attached devices (sensors) like this:

iNumOfSens = sensors.getDeviceCount();

Then I want to send collected Temperature data one by one...

Here is my current Serial output (it's only updates the last one like you said from the beginning):

/json.htm?type=command&param=udevice&hid=1&did=00&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=24.44
/json.htm?type=command&param=udevice&hid=1&did=01&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=25.19
/json.htm?type=command&param=udevice&hid=1&did=02&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=24.69

HTTP/1.1 200 OK
Content-Length: 53
Content-Type: application/json;charset=UTF-8
Cache-Control: no-cache
Pragma: no-cache
Access-Control-Allow-Origin: *

{
   "status" : "OK",
   "title" : "Update Device"
}

But I wish to do it like this:

Read the first, send to the server
Read the second, send to the server
Read the third, send to the server
etc,...

/json.htm?type=command&param=udevice&hid=1&did=00&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=24.44

HTTP/1.1 200 OK
Content-Length: 53
Content-Type: application/json;charset=UTF-8
Cache-Control: no-cache
Pragma: no-cache
Access-Control-Allow-Origin: *

{
   "status" : "OK",
   "title" : "Update Device"
}

/json.htm?type=command&param=udevice&hid=1&did=01&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=25.19

HTTP/1.1 200 OK
Content-Length: 53
Content-Type: application/json;charset=UTF-8
Cache-Control: no-cache
Pragma: no-cache
Access-Control-Allow-Origin: *

{
   "status" : "OK",
   "title" : "Update Device"
}

/json.htm?type=command&param=udevice&hid=1&did=02&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=24.69

HTTP/1.1 200 OK
Content-Length: 53
Content-Type: application/json;charset=UTF-8
Cache-Control: no-cache
Pragma: no-cache
Access-Control-Allow-Origin: *

{
   "status" : "OK",
   "title" : "Update Device"
}

and then it will all start from the beginning.

My current code is working good but I just need to fix that current FOR LOOP somehow.

char oneSensorsData[20];
char xUrl[200] = "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0";

for(int iCount = 0; iCount < iNumOfSens; iCount++)
{
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);

    sprintf(oneSensorsData, "&svalue%d=%d", iCount, sTempC);

    strcat(xUrl, oneSensorsData);
}

After this loop, print xUrl. Does it contain what you expect? What happens when you send that string to the server?

but there is no For loop

The for loop I deconstructed for my code.

             for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
             client.print("analog input ");
             client.print(analogChannel);
             client.print(" is ");
             client.print(analogRead(analogChannel));
             client.print("
");
             }

PaulS:

char oneSensorsData[20];

char xUrl[200] = "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0";

for(int iCount = 0; iCount < iNumOfSens; iCount++)
{
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);

sprintf(oneSensorsData, "&svalue%d=%d", iCount, sTempC);

strcat(xUrl, oneSensorsData);
}




After this loop, print xUrl. Does it contain what you expect? What happens when you send that string to the server?

I'm sending two type of data in that constructed link/Url:

That construction happens at this line (sprintf) in my original code on the top of my topic:

for (int iCount = 0; iCount < iNumOfSens; iCount++) {
    memset(sTempC, 0, sizeof(sTempC));
    float fTempC = sensors.getTempCByIndex(iCount);
    dtostrf(fTempC, 5, 2, sTempC);
    sprintf(xUrl, "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=%s", iCount, sTempC);
    
    ether.browseUrl(PSTR(""), xUrl, sServer, brw_cb);
    
    Serial.println(xUrl);
   }

Where iCount is for the current ID of the sensor and the sTempC is for the sensor Value.

So, in the FOR procedure in sprintf Url happens this:

in the did=0%d Url part goes iCount value
in the svalue=%s Url part goes sTempC value

I'm sending two type of data in that constructed link/Url:

The code that deals with the data does not care what order the name=value pairs are in. Separating the data that far makes it harder to see that there are two name=value pairs that are related.

Not that it matters, since the technique I described can easily be changed to output two name=value pairs, except that you need to remove both of the name=value pairs from the base string.

Where iCount is for the current ID of the sensor

I'm sorry, but iCount is a crappy name for sensor number. The rest of the question isn't really clear, but %d is the format specifier for an int and %s is the format specifier for a string.

PaulS:
The code that deals with the data does not care what order the name=value pairs are in. Separating the data that far makes it harder to see that there are two name=value pairs that are related.

Not that it matters, since the technique I described can easily be changed to output two name=value pairs, except that you need to remove both of the name=value pairs from the base string.

Ohhh PaulS, you are trying to help me with the code what is working from the beginning, don't mention that URL again it's all good!

PaulS:
I'm sorry, but iCount is a crappy name for sensor number. The rest of the question isn't really clear, but %d is the format specifier for an int and %s is the format specifier for a string.

Yeah, you are right about that, I changed it!

But, nerveless, here is what I was looking for, I just removed FOR and added some simple code, I figured it about 5 min. ago.

Please look at my new code snippet:

void loop () {
 ether.packetLoop(ether.packetReceive());
  
 if (millis() > timer) {
  timer = millis() + 4000;

  sensors.requestTemperatures();
 
  memset(xUrl, 0, sizeof(xUrl));
  
  if (iCurSens == iMaxSens){
   iCurSens=0;
  }else{
   iCurSens++;
  }
  
  float fRawSensTemp = sensors.getTempCByIndex(iCurSens);
    
  dtostrf(fRawSensTemp, 5, 2, iCurSensTemp);
 
  sprintf(xUrl, "/json.htm?type=command&param=udevice&hid=1&did=0%d&dunit=1&dsubtype=9&dtype=80&nvalue=0&svalue=%s", (iCurSens+1), iCurSensTemp);
 
  Serial.println();
  Serial.println(xUrl); 
  
  ether.browseUrl(PSTR(""), xUrl, srvIpAddr, eth_callback);
  
  }
}

And tell me what you think about it!

Please look at my new code snippet:

Ooooo.... 8)

Please look at my new code snippet:

Pretty. It still sends one reading at a time. I guess, since you seem happy with the code, that you've changed your requirements. That's one solution, I guess.

PaulS:
Pretty.

Thanks! :smiley:

PaulS:
It still sends one reading at a time.

Who told you that I wish more than one readings at a time, where did I wrote that?!? :wink:

zoomkat:
Ooooo.... 8)

LEL :smiley: