Pages: 1 [2]   Go Down
Author Topic: DHT22 and mySQL error (%d)  (Read 4115 times)
0 Members and 1 Guest are viewing this topic.
Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 116
Posts: 5398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Upload this and watch the serial monitor. I think this is what you want.
Code:
float temp = 70.10;
float humidity = 41.23;

void setup()
{
  Serial.begin(9600);  
}

void loop()
{
  char tBuffer[16];
  char hBuffer[16];
  char outBuffer[64];

  sprintf(outBuffer,"temp: %s humidity: %s",dtostrf(temp,8,2,tBuffer),dtostrf(humidity,8,2,hBuffer));
  
  Serial.println(outBuffer);
  delay(1000);
  temp = temp + 1.1;  
  humidity = humidity - 0.01;
}

Edit: I see wildbill hit it right on.
« Last Edit: September 18, 2011, 08:47:22 am by SurferTim » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


tBuffer and hBuffer are a bit oversized, 8 positions should be enough with 2 decimals (do you really need 2?) ,

check layout: "-ddd.dd\0" temp and humidity will never need more positions I guess...




Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 116
Posts: 5398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You are correct. The buffers are a bit oversized.

Actually, I was working on something else that requires more buffer space. There are some characters that may need to be url escaped when placed in a url. When I call the function below, it could use more buffer space. This routine escapes the characters in the original character array.

I could not find this in a library anywhere, so I wrote my own.

Code:
void urlencode(char* _str)
{
  int x,y;
  char hexBuffer[3];
  
  for(x = (strlen(_str) - 1); x >= 0; x--)
  {
    switch(_str[x])
    {
      case '"' :
      case ' ' :
      case '/' :
      case '+' :
      case '<' :
      case '>' :
      case '#' :
      case '%' :
      case '{' :
      case '}' :
      case '|' :
      case '\\' :
      case '^' :
      case '~' :
      case '[' :
      case ']' :
      case '`' :
      case ';' :
      case '?' :
      case ':' :
      case '@' :
      case '=' :
      case '&' :
      case '$' :

      for(y = strlen(_str); y > x;y--)
      {
        _str[y + 2] = _str[y];
      }

      sprintf(hexBuffer,"%2x",_str[x]);
      
      _str[x] = '%';
      _str[x+1] = hexBuffer[0];
      _str[x+2] = hexBuffer[1];
      break;
      
    }
  }
}

BTW, the buffer might come close to overflowing even at 16. There are at least a few leading spaces that will be encoded unless they are trimmed.

Code:
void trim(char* _str)
{
  while( (strlen(_str) > 0) && (_str[0] == 32) )
  {
     strcpy(_str,&_str[1]);
  }

  while( (strlen(_str) > 0) && (_str[strlen(_str) - 1] == 32) )
  {
    _str[strlen(_str) - 1] = 0;
  } 
}
« Last Edit: September 18, 2011, 12:16:30 pm by SurferTim » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

looks nice and robust,

but in your urlencode() if there are a more than 1 special chars you move many chars multiple times. Would it not be more efficient to have a first iteration through the string to know how many chars need to be escaped?

if (escapes == zero) return;

if more than zero => you can move the other chars immediately in the right position.
Then insert the escaped string directly on the right spot


Finally, maybe the signature of the function should be char * so you can use the function as param for print or so
Code:
char* urlencode(char* _str)
{
  ...

  return _str;
}

update:
A quick and dirty implementation of the above increased the footprint with 130 bytes and was 20-25% faster with a complex test string. So it becomes speed versus memory again. 
« Last Edit: September 18, 2011, 12:53:58 pm by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 116
Posts: 5398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@robtillaart: Thanks. And thanks for the tip on the '%f'. That would have been a surprise.

If there are no special characters, it only goes through once, never executing the 'y' loop.

If a special character is encountered, the 'y' loop moves everything after that character two characters toward the end of the string, so there will be room for that character to be encoded.

Maybe a little on the "bubble sort" edge of primitive, but it works.

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12483
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Maybe a little on the "bubble sort" edge of primitive, but it works.

I recognized the bubble effect and from bubble sort we know that has quite a bad performance in worst case. Imagine a string consisting of chars that all need to be escaped. that is a lot of repeated moves

That triggered me to think if you could move the chars in one step to their final position. But that meant #chars to be escaped should be known, => a second loop to scan the string before the moves could be done. That second loop caused the footprint to grow... (due to the "big switch") ...


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Harlow, Essex, UK
Offline Offline
Jr. Member
**
Karma: 1
Posts: 67
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Many thanks for your help guys smiley

Having posted the non-working code originally, I thought I would now post the working code incase its of any assistance for someone in the future.

Thanks again.

Code:
void getTemp (){
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float humidity = dht.readHumidity();
  float temp = dht.readTemperature();

  char tBuffer[8];
  char hBuffer[8];
  char strURL[64];

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(temp) || isnan(humidity)) {
    Serial.println("Failed to read from DHT");
  } else {
      Serial.println("connected, writing ...");
      Serial.print("Humidity: ");
      Serial.print(humidity);
      Serial.print(" %\t");
      Serial.print("Temperature: ");
      Serial.print(temp);
      Serial.println(" *C");     
      delay(50);
      sprintf(strURL,"GET /arduino/arduino_push_output.php?t=%s&h=%s",dtostrf(temp,4,2,tBuffer),dtostrf(humidity,4,2,hBuffer));
      client.println(strURL);
      client.println();
      Serial.println(strURL);
  }
}
Logged

Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 116
Posts: 5398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hope it doesn't get cold where you are. When the temperature drops below 10 degrees C, the send will fail. There will be a leading space on the temperature.

I recommend one of the choices below:
1) the trim() function I posted to remove those leading and trailing spaces.
2) do it yourself with your own code
3) use the urlencode() function and that will change the space into a %20.

Add: The new function that we are using above works a bit different than ' %f '. The function the way you are now calling it, will put the converted value into the character buffer using a maximum of 4 characters, two characters right of the decimal point.
dd.dd

This function right justifies that buffer, filling the left characters with spaces. When the temperature drops below "10.00", there will be a leading space. " 9.99"


« Last Edit: September 19, 2011, 08:43:44 am by SurferTim » Logged

Harlow, Essex, UK
Offline Offline
Jr. Member
**
Karma: 1
Posts: 67
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I live in the UK, our summers are often sub 10 degrees C smiley

Can you illustrate using my code who I would add the trim() function, I see its another function call, but unsure on how to instigate it.

Many thanks,

Steve
Logged

Miramar Beach, Florida
Online Online
Faraday Member
**
Karma: 116
Posts: 5398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Trim is easy.

This is how I tested that function. When you run it, it changes the values once a second, trims and converts the strings, and then sends it to the serial display like your request will look.

I included urlencode, which if you use this type of GET send, you will need. The example show how to use it too.

The urlencode should be used with caution. It is easy to overflow the buffer that your original string is in. To be absolutely safe, the formula for the buffer size should be ((n * 3) +1) characters in size, where n = originalStringLength. If there will be 5 characters, then 16 is the absolute safe value. But here you know a few will be numbers.

Code:
float temp = 80.10;
float humidity = 41.23;

void setup()
{
  Serial.begin(9600); 
}

void trim(char* _str)
{
  while( (strlen(_str) > 0) && (_str[0] == 32) )
  {
     strcpy(_str,&_str[1]);
  }

  while( (strlen(_str) > 0) && (_str[strlen(_str) - 1] == 32) )
  {
    _str[strlen(_str) - 1] = 0;
  } 
}

void urlencode(char* _str)
{
  int x,y;
  char hexBuffer[3];
 
  for(x = (strlen(_str) - 1); x >= 0; x--)
  {
    switch(_str[x])
    {
      case '"' :
      case ' ' :
      case '/' :
      case '+' :
      case '<' :
      case '>' :
      case '#' :
      case '%' :
      case '{' :
      case '}' :
      case '|' :
      case '\\' :
      case '^' :
      case '~' :
      case '[' :
      case ']' :
      case '`' :
      case ';' :
      case '?' :
      case ':' :
      case '@' :
      case '=' :
      case '&' :
      case '$' :

      for(y = strlen(_str); y > x;y--)
      {
        _str[y + 2] = _str[y];
      }

      sprintf(hexBuffer,"%2x",_str[x]);
     
      _str[x] = '%';
      _str[x+1] = hexBuffer[0];
      _str[x+2] = hexBuffer[1];
      break;
     
    }
  }
}


  char tBuffer[16];
  char hBuffer[16];
  char outBuffer[128];

void loop()
{
  dtostrf(temp,8,2,tBuffer);
  trim(tBuffer);
  urlencode(tBuffer);

  dtostrf(humidity,8,2,hBuffer); 
  trim(hBuffer);
  urlencode(hBuffer);

  sprintf(outBuffer,"GET /arduino/arduino_push_output.php?t=%s&h=%s",tBuffer,hBuffer);
 
  Serial.println(outBuffer);
 
  delay(1000);
  temp = temp + 1.1; 
  humidity = humidity - 0.01;
}

I hope I did not introduce any typos transferring it here.
Logged

Pages: 1 [2]   Go Up
Jump to: