OLEDMote display of sensor values

Started by Stark, January 06, 2015, 05:40:35 PM

Stark

Hi and Happy New Year.

I am yet another newbie to programming and have an OLEDMote which I am wishing to display temperature/sensor readings.

My problem, I can get the Node.ino sketch to send to my OLEDMote and display the 123 ABC...output but am having problems when sending values from a sensor. The sensor is set up and prints ok to the serial port. I then incorporated the sensor code into the Struct_send sketch. However the OLEDMote receiver is displaying garbled messages instead of the temperature reading.

I figured that the issue was related to the fact that the temperature readings are taken as double float variables which cannot be displayed on the OLED. I have attempted to convert the double float to char in the hope that my fiddling will work.

Alas this is not working and my lack of knowledge is letting me down!

Excerpts of code below to give you the general idea.

char temp[10];
typedef struct {		
  char* tempstr;
} Payload;
Payload theData;

dtostrf(T,2,2,temp); //where T is declared as a double float variable and obtained from the temperature sensor

theData.tempstr = temp; 
    
    Serial.print("Sending struct (");
    Serial.print(sizeof(theData));
    Serial.print(" bytes) ... ");
    if (radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)))
      Serial.print(" ok!");
    else Serial.print(" nothing...");


I'm sure someone can give me some pointers. In the meantime I will go away and learn more about strings and variables. Thanks and regards.

Felix

Try
dtostrf(T,3,2, buff);
where buff should be a char array with enough space to hold the generated value you're expecting. Ie something like char[20] buff;
Or you can declare it as a predefined array which is the largest string you'd ever expect:

char* buff="99999.99";

TomWS

Quote from: Stark on January 06, 2015, 05:40:35 PM
Hi and Happy New Year.

I am yet another newbie to programming and have an OLEDMote which I am wishing to display temperature/sensor readings.

My problem, I can get the Node.ino sketch to send to my OLEDMote and display the 123 ABC...output but am having problems when sending values from a sensor. The sensor is set up and prints ok to the serial port. I then incorporated the sensor code into the Struct_send sketch. However the OLEDMote receiver is displaying garbled messages instead of the temperature reading.

I figured that the issue was related to the fact that the temperature readings are taken as double float variables which cannot be displayed on the OLED. I have attempted to convert the double float to char in the hope that my fiddling will work.

Alas this is not working and my lack of knowledge is letting me down!

Excerpts of code below to give you the general idea.

char temp[10];
typedef struct {		
  char* tempstr;
} Payload;
Payload theData;

dtostrf(T,2,2,temp); //where T is declared as a double float variable and obtained from the temperature sensor

theData.tempstr = temp; 
    
    Serial.print("Sending struct (");
    Serial.print(sizeof(theData));
    Serial.print(" bytes) ... ");
    if (radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)))
      Serial.print(" ok!");
    else Serial.print(" nothing...");


I'm sure someone can give me some pointers. In the meantime I will go away and learn more about strings and variables. Thanks and regards.
In your example you don't need the structure 'theData' and, in fact, this is a large part of your problem.  What is the sizeof(theData)?  I think it is the size of a Moteino address pointer... which is what you've declared 'theData' to contain.

Why not try something simple like:
   radio.sendWithRetry(GATEWAYID, &temp, sizeof(temp));

Also, I'm with Felix on making temp larger IF you REALLLLLLLLLLLLLLY need a 'double' value...   ::)

TomWS

By the way, what OLED display are you using?
I'd really like to find an easy to use, low power one...

Tom

Felix

I use SSD1306_128X64 OLEDs in my OLEDMote kits. You can find them on ebay usually. They are fairly low power, and consumption is proportional to how many pixels are lit.

Stark

Many thanks for the help. Success!

Increasing the char array buffer didn't work fully.
The use of the structure 'thedata' seems to be the problem as suggested. Trying the following worked removing structure 'thedata'.

radio.sendWithRetry(GATEWAYID, &temp, sizeof(temp));


I do actually intend to send other variables with the temp. I.e pressure, lux etc up to the length of characters that can be displayed on the OLED. It's a shame as 'thedata' structure was a tidy way to do it.

Will next work on stringing the variables together to send and display what I intend such as
T:23.0, P:1030.0. Where P is also a variable.

Incidentally the double float is all I can get from the sensor.

Thanks again and any further comment and suggestions will be gratefully received.

ColinR

How big's the library for those things?
CuPID Controls :: Open Source browser-based sensor and device control
Interfaceinnovations.org/cupidcontrols.html
cupidcontrols.com

TomWS

Quote from: Stark on January 08, 2015, 03:00:14 AM
Many thanks for the help. Success!

Increasing the char array buffer didn't work fully.
The use of the structure 'thedata' seems to be the problem as suggested. Trying the following worked removing structure 'thedata'.

radio.sendWithRetry(GATEWAYID, &temp, sizeof(temp));


I do actually intend to send other variables with the temp. I.e pressure, lux etc up to the length of characters that can be displayed on the OLED. It's a shame as 'thedata' structure was a tidy way to do it.

Will next work on stringing the variables together to send and display what I intend such as
T:23.0, P:1030.0. Where P is also a variable.

Incidentally the double float is all I can get from the sensor.

Thanks again and any further comment and suggestions will be gratefully received.
Stark, you can send any structure you want.  You just need to construct it properly so that you're sending the 'content'.  In your original code, you were sending the 'address' of the content.   Something that is easily confusing for programmers new to C.

Here is are two examples of sending 'structured' content.  The first one contains text formatted data, as you are trying to send now.
char txbuf[60];
float temp, pressure;   // I'm using float because it's easier to manage and you won't have a significant loss of precision

   temp=readYourTempSensor();
   pressure=readYourPressureSensor();
   byte len = sprintf(txbuf, "T:%3.1f, P:%5.1f", temp, pressure);  // sprintf does the magic but you might have to set some IDE flags to get floating point support...
   radio.sendWithRetry(GATEWAYID, txbuf,len);


Or, if you want to be super efficient at your mote, don't worry about formatting, just send the raw data:
struct MY_PACKET {
    float temp, pressure;   // I'm using float because it's easier to manage and you won't have a significant loss of precision
} my_packet;
   my_packet.temp=readYourTempSensor();
   my_packet.pressure=readYourPressureSensor();
   radio.sendWithRetry(GATEWAYID, &my_packet,sizeof(my_packet));

In this case the receiving end MUST know how the packet is structured AND must use the same internal representation for 'float' (byte order and size).

Tom

TomWS

Quote from: Felix on January 06, 2015, 10:29:26 PM
I use SSD1306_128X64 OLEDs in my OLEDMote kits. You can find them on ebay usually. They are fairly low power, and consumption is proportional to how many pixels are lit.
Thanks Felix, I'll check it out.

Stark

#9
Quotechar txbuf[60];
float temp, pressure;   // I'm using float because it's easier to manage and you won't have a significant loss of precision

   temp=readYourTempSensor();
   pressure=readYourPressureSensor();
   byte len = sprintf(txbuf, "T:%3.1f, P:%5.1f", temp, pressure);  // sprintf does the magic but you might have to set some IDE flags to get floating point support...
   radio.sendWithRetry(GATEWAYID, txbuf,len);

Thanks Tom for the concise response. Finally I understand the options on sending!

The main constraint is the OLED as it needs text formatted data on the receiving end to display correctly.

I have adapted your example code above but first converting the double into char using the dtostrf function to one decimal place, then I use the sprintf with an 's' ide flag i.e "T:%s, P:%s".

As said earlier the sensor library does not have a function to allow the return float or integer values. It will only accept the temperature and pressure declared as double float variables. Tried float and compiling returned a function not found error.

I could have gone with the second example of sending the raw data but the OLEDMote sketch expects a char variable for the data. At some point I would need to convert  for OLED display so it makes it simpler for me programming wise to keep this on the transmitting end for now. The OLEDMote captures all network data packets so this could be complicated if I had too many variables.

Thanks again, your help has given me a good knowledge for moving forward. Just need now to save power on both the sensor and OLED end.

Quote from: ColinR on January 08, 2015, 04:23:09 AM
How big's the library for those things?

Colin, to clarify I have different sensors, a DHT22 (temp and humidity), a BMP180 (pressure and temperature) and a TSL2561 luminosity sensor. They are using the standard libraries available from the supplier. I don't intend to use all on single node but could have a combination of lux and temp on one node.

As some further background, the luminosity sensor I want to deploy located outside on my fire escape walkway to allow control of the switching of some house lights. The temp and humidity sensors mainly to allow me to worry about the weather and the contents of my remote garage.(as well as proving to the wife she married a geek)!

I live on the third floor of a brick and concrete apartment building and the RFM69HW works nicely with the 25m or so distances involved to the garage.

TomWS

Quote from: Stark on January 10, 2015, 05:11:38 PM
<...snip>

As said earlier the sensor library does not have a function to allow the return float or integer values. It will only accept the temperature and pressure declared as double float variables. Tried float and compiling returned a function not found error.

What does your sensor library function call look like?  Are you passing addresses of your variables or do you get the sensor value as the return value of the function call?

If you can post the function prototypes (from the .h file), that would be useful.

Tom

Stark


TomWS

Quote from: Stark on January 10, 2015, 05:27:08 PM
Quote from: TomWS on January 10, 2015, 05:20:12 PM

If you can post the function prototypes (from the .h file), that would be useful.


Hi Tom

The library .h is here;

https://github.com/sparkfun/BMP180_Breakout/blob/master/software/Arduino/libraries/SFE_BMP180/SFE_BMP180.h

Regards, Stark
BOSCH! I should have known!  Only THEY would use a double value for a pressure sensor that probably has no better than 0.1% accuracy!

Ok, I yield, you do need a double.  Bosch wins   :D 

Tom

Stark

  ;D I know it doesn't make any sense and it was probably the worst sensor I could have chosen to get started with!

Thanks for your help and advice.

TomWS

Quote from: Stark on January 10, 2015, 05:58:39 PM
  ;D I know it doesn't make any sense and it was probably the worst sensor I could have chosen to get started with!

Thanks for your help and advice.
No, it's actually a darned good sensor.  It's a lousy library, but a good sensor...
The absolute accuracy of the sensor is -0.4%+0.2% on pressure and +/-1 degree C on temperature.  Using doubles for this kind of data is terribly inefficient. 
But maybe Sparkfun developed it under contract to Bosch using Bosch's design requirements...  ;)
And hopefully you are now enjoying the very precise data you are gathering!

Tom