Problem with byte values when trying to create classes

Hello all,

I have an issue for my first Arduino (Uno) project I want to use the KY015 temperature and humidity sensor, I have looked for a tutorial how to use it and found a fantastic one here: TkkrLab

When I use this code in a sketch is works like a charm, BUT I want to make it in to my own library, to have less clutter in the sketch file, so I decided to create a class out of it. To make programming a little easier I have decided to use Eclipse IDE with the Arduino Plugin (from http://eclipse.baeyens.it/)

Now I have the strangest behaviour, the values I am getting back from the class a not correct, at least as far I know it is not 224C and the humidity is not 210%. I am sure there is some type conversion problem going on here, but I cannot find out how and why, the funny thing is:

  • When I compile my project with classes with the Arduino IDE everything works fine, correct temperature and humidity values
  • When I compile the example sketch with the Arduino IDE everything works fine, correct temperature and humidity values
  • When I compile the example sketch with the Eclipse IDE with Arduino plugin everything works fine, correct temperature and humidity values

BUT

  • When I compile my project with classes with the Eclipse IDE with Arduino plugin the strangest temperature and humidity values are displayed

Has anyone seen this behaviour? And where could the problem be? It almost looks like a compiler option which is wrong in the Eclipse IDE with Arduino plugin.

Kind regards,

Raymond

To make programming a little easier I have decided to use Eclipse IDE with the Arduino Plugin (from http://eclipse.baeyens.it/)

Did that really make programming easier?

as far I know it is not 224C and the humidity is not 210%.

Do you have some proof of that? 8)

I am sure there is some type conversion problem going on here, but I cannot find

any code to prove that. At least, I can't.

BUT

When I compile my project with classes with the Eclipse IDE with Arduino plugin the strangest temperature and humidity values are displayed

If the code compiles, the results really should be the same.

Did that really make programming easier?

Initially it did make programming easier, only it introduced this strange behaviour. But I am guessing this would be pretty much the same as with making libraries.

Do you have some proof of that? 8)

Ohh proof, well I did not melt and did not drown 8)

If the code compiles, the results really should be the same.

That is what I thought, yet there is a difference

I have created a class, regarded the return values an made the functions of the same datatype, and I basicly copy pasted the example sketch functions in the class, with some minor changes regarding the pinnumber variable and turned a global variable in to a local one.

Why not just show us the class, the sketch that uses the class, and the correct (compiled and linked by the IDE) output and the incorrect (compiled and linked by the interloper) output?

Perhaps a clue-by-four will present itself.

I just started, so it is not mucht yet, but here is the class and the sketch

My header file looks like this:

#ifndef KY015_h
#define KY015_h

#include "Arduino.h"

class KY015
{
   	private:
		int temperature;
		int humidity;
		int _pinNumber;
		byte r_KY015_data();
		void read_KY015();
	public:
		KY015(int pinNumber);
		void read();
		int getTemperature();
		int getHumidity();
		int getPinNumber();
};

#endif

The corresponding .cpp file looks like this

#include "KY015.h"

KY015::KY015(int pinNumber)
{
    _pinNumber = pinNumber;
    pinMode (_pinNumber, OUTPUT);
}

byte KY015::r_KY015_data()
{
  byte KY015data;
  for (int i = 0; i < 8; i ++) {
    if (digitalRead (_pinNumber) == LOW) {
      while (digitalRead (_pinNumber) == LOW); // wait for 50us
      delayMicroseconds (30); // determine the duration of the high level to determine the data is '0 'or '1'
      if (digitalRead (_pinNumber) == HIGH)
        KY015data |= (1 << (7-i)); // high front and low in the post

      while (digitalRead (_pinNumber) == HIGH); // data '1 ', wait for the next one receiver
     }

  }

  return KY015data;
}

void KY015::read_KY015()
{
  byte KY015dat [5];
  digitalWrite (_pinNumber, LOW); // bus down, send start signal
  delay (30); // delay greater than 18ms, so DHT11 start signal can be detected

  digitalWrite (_pinNumber, HIGH);
  delayMicroseconds (40); // Wait for DHT11 response

  pinMode (_pinNumber, INPUT);
  while (digitalRead (_pinNumber) == HIGH);
  delayMicroseconds (80); // DHT11 response, pulled the bus 80us
  if (digitalRead (_pinNumber) == LOW){
  delayMicroseconds (80); // DHT11 80us after the bus pulled to start sending data
  }
  for (int i = 0; i < 4; i ++) // receive temperature and humidity data, the parity bit is not considered
	  KY015dat[i] = r_KY015_data ();

  pinMode (_pinNumber, OUTPUT);
  digitalWrite (_pinNumber, HIGH); // send data once after releasing the bus, wait for the host to open the next Start signal

  humidity = (KY015dat [0]);
  temperature = (KY015dat [2]);
}

void KY015::read()
{
  read_KY015();
}

int KY015::getTemperature()
{
  return temperature;
}

int KY015::getHumidity()
{
  return humidity;
}

int KY015::getPinNumber()
{
  return _pinNumber;
}

The sketch looks like this:

//Include libraries
#include <Arduino.h>
#include "KY015.h"

//Define Digitalpin names
#define KY015_INTERNAL 8

//Declare objects
KY015 KY015_INT(KY015_INTERNAL);
long previousMillis = 0;
long interval = 2500;

void setup()
{
    Serial.begin(9600);
	Serial.print("Refreshing with an interval of: "); Serial.print(interval); Serial.println(" miliseconds.");

}

void loop()
{
    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis > (unsigned long) interval){
        previousMillis = currentMillis;

        Serial.print("Reading KY015_Internal values on pin: "); Serial.println(KY015_INT.getPinNumber());
        KY015_INT.read();

        Serial.print("KY015_Internal sensor values are: ");
        Serial.print(KY015_INT.getTemperature()); Serial.print(" C and ");
        Serial.print(KY015_INT.getHumidity()); Serial.println(" %.");
    }

}

I have attached the compiled file which is uploaded to the arduino.

I hope you will see the problem I am not seeing at the moment.

Kind regards,

Raymond

Fermentator.hex.zip (3.25 KB)

Ohh by the way the Attached file is the one that gives me the "strange" numbers.

KY015::KY015(int pinNumber)
{
    _pinNumber = pinNumber;
    pinMode (_pinNumber, OUTPUT);
}

You should not be diddling with pin modes in the constructor. You do not know that the hardware is ready when your constructor is called.

It is possible that Eclipse has a different idea what size a byte is than the IDE does. Since ints don't seem to be impacted, perhaps the thing to do is to not try to save one byte, and just use int. Or, use uint8_t instead of byte. The _t means that the size of the type is going to be consistent everywhere.

PaulS:
You should not be diddling with pin modes in the constructor. You do not know that the hardware is ready when your constructor is called.

Agreed. I always create a setup() and a loop() in my classes, even if they do nothing, and call them from the main setup and loop.

a begin() method is kind of the Arduino way of calling it. And update() kind of the Arduino "standard" for a loop() method. Calling it loop() is a bit confusing because in contrast with the Arduino loop() function it does not automatically loop.

Hi,

Sorry for the late reply. I have been tinkering with met sketch and decided to restart from scratch, because I did notice I was mixing up some different versions is the sketch I was using. But fixed that and now it seems to work without a problem. I will keep in mind though what you said about changing pin-modes in a constructor. Up till now it seems to work without problems though.

I would also like to create a class to initialise the SD card reader and to write to the SD card. When using the class it just does not want to work, when I do it in the main sketch it does work, I guess that is similar to the pinmode thing, where it is not known whether the hardware is ready.

Regards,

Raymond

So you're still relying on a pinMode() in the constructor? I would not do that. Might work now but might not work in the future (IDE update for example or other sketch). I would hate a reliability like that. Just make a begin() method and call it in setup().

When using the class it just does not want to work

You need to make your class derive from WantsToWork.