Go Down

Topic: Division Problem (Read 7852 times) previous topic - next topic

PaulS

Code: [Select]
  #ifndef verbose
  servoPosition = 255*servoPercentage;
  servoPosition /= 100;
  #endif
 
#ifdef verbose
  Serial.print("servoPercentage=");
  Serial.println(servoPercentage,DEC);
  servoPosition = 255*servoPercentage;
  Serial.print("servoPosition[*255]=");
  Serial.println(servoPosition,DEC);
  servoPosition /= 100;
  Serial.print("servoPosition[/100]=");
  Serial.println(servoPosition,DEC);
#endif

Calculate a new value if verbose is not defined. Print it if it is. OK.
The art of getting good answers lies in asking good questions.

howroyd

I'm not sure I follow what you mean paul?

I think I've found the problem was because I was using pointers to classes and I c**ked it up.  So I've taken the memory and speed hit & have memory copying everywhere.  Now I have all the calculations running as they should be.

I really appreciate all the help everyone has given, cheers!

PaulS

Quote
I'm not sure I follow what you mean paul?

You have this:
Code: [Select]
  #ifndef verbose
  servoPosition = 255*servoPercentage;
  servoPosition /= 100;
  #endif

The ifndef preprocessor directive says to compile this block of code if verbose is NOT defined. When verbose IS defined, this code is NOT compiled.

Then, you have this:
Code: [Select]
#ifdef verbose
  Serial.print("servoPercentage=");
  Serial.println(servoPercentage,DEC);
  servoPosition = 255*servoPercentage;
  Serial.print("servoPosition[*255]=");
  Serial.println(servoPosition,DEC);
  servoPosition /= 100;
  Serial.print("servoPosition[/100]=");
  Serial.println(servoPosition,DEC);
#endif

The ifdef preprocessor directive says to compile this block of code if verbose is defined. When verbose IS defined, this code is compiled.

So, if verbose is defined, printing occurs, but calculations do not.
If it is not defined, calculations are performed, but not printed.
The art of getting good answers lies in asking good questions.

AWOL

Quote
So, if verbose is defined, printing occurs, but calculations do not.
If it is not defined, calculations are performed, but not printed.

It doesn't read that way to me (it's been a long day), but certainly the calculation should not be conditional upon anything.

howroyd

Quote
So, if verbose is defined, printing occurs, but calculations do not.
If it is not defined, calculations are performed, but not printed.


But the same calculations are in both??

Code: [Select]
#ifdef verbose
  Serial.print("servoPercentage=");
  Serial.println(servoPercentage,DEC);
  servoPosition = 255*servoPercentage;    // <--------------HERE
  Serial.print("servoPosition[*255]=");
  Serial.println(servoPosition,DEC);
  servoPosition /= 100;                         // <--------------HERE
  Serial.print("servoPosition[/100]=");
  Serial.println(servoPosition,DEC);
#endif

nickgammon



Quite annoying.  There should be only one instance of the class being opened in the main loop:
Code: [Select]
void loop()
{
 adc * myAdc;             // Construct the ADC class
 hController * hControl;  // Construct the H2 flow control class
 time * myTime;           // Construct the Time class
 int pos=1;
 int flip=false;

 while(true){
hControl->servoControl((int)pos);
myTime->realtime();}
}

There's a lot more of code in the while loop but nothing that would conflict


That code looks quite wrong. I hope there is more in loop than that, and if so it might help to show it.

To summarize the problem:

Code: [Select]
  hController * hControl;  // Make an uninitialized pointer to an hController class

...

hControl->servoControl((int)pos);  // dereference that pointer, very probably corrupting memory



I don't like your use of the words "Construct the H2 flow control class" - that code is not constructing anything. Also, why set up a pointer to the class in loop? If you are, further down, doing a malloc to make hControl point to some valid memory (and not just random memory) then the class constructor won't be called.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

PeterH


I'm not sure I follow what you mean paul?

I think I've found the problem was because I was using pointers to classes and I c**ked it up.  So I've taken the memory and speed hit & have memory copying everywhere.  Now I have all the calculations running as they should be.

I really appreciate all the help everyone has given, cheers!


Glad you have found the problem. In my experience, if the behaviour defies common sense it is almost certainly because of a false assumption. If you come to the conclusion that the arithmetic operators are producing incorrect answers, you would in effect be assuming that nothing else happening is relevent to the behaviour of those few lines of code. So take everything else away, and prove your assumption is valid. In this case, clearly you've found that was not a valid assumption.

howroyd

#22
Nov 17, 2011, 01:32 am Last Edit: Nov 17, 2011, 01:58 am by howroyd Reason: 1
Hi Nick,

I am new to cpp and think that my understanding of pointers to classes is completely wrong.

What I was trying to do was create an instance of the class, which would use the default constructor in the class, public scope.  Then run the method servoControl.

Whenever I tried to create instances in the setup() it always said in the loop() that servoControl was outside the scope of the loop, or something similar.  Hence why I created the instances in loop() then had a while() after that, so a sort of initialisation.

I've done a fair amount of reading on pointers to classes but don't get what ive done wrong.  It's not an issue because ive declared it now without it being a pointer, but the time will come when memory runs out... Hopefully I'll understand by then!

Thanks

ps: there is no malloc or anything in the while loop.  the only relevent stuff is listed, which is pretty bare!

EDIT:
If I were to do the following (just trying to get this right for my own piece of mind!), would this be valid so I can then use pHControl->function();?
Code: [Select]
  adc   myAdc;
  adc *pMyAdc = &myAdc;
  hController  hControl;
  hController *pHControl  = &hControl;
  time         myTime;
  time *pMyTime = &myTime;

GoForSmoke

I would still like to see Serial.print(bytevar, HEX) only generate 2 hex characters.

1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

nickgammon

#24
Nov 17, 2011, 06:40 am Last Edit: Nov 17, 2011, 06:42 am by Nick Gammon Reason: 1


EDIT:
If I were to do the following (just trying to get this right for my own piece of mind!), would this be valid so I can then use pHControl->function();?
Code: [Select]
 adc   myAdc;
 adc *pMyAdc = &myAdc;
 hController  hControl;
 hController *pHControl  = &hControl;
 time         myTime;
 time *pMyTime = &myTime;



Well, you can but I don't see the point.

The most reasonable thing, probably, is to declare them outside any function. Then they have global scope. However do not do anything important inside the constructor (because of issues about which things are constructed in which order). Instead make a begin () function and call that. So your code might look like this:

Code: [Select]
// global variables are being instantiated
adc   myAdc;
hController  hControl;
time         myTime;

void setup ()
{
 myAdc.begin ();  // do any necessary initialization
 hControl.begin ();  // ditto
 myTime.begin ();  // ditto
} // end of setup

void loop ())
{
 myAdc.whatever ();
...
}  // end of loop



Quote
I've done a fair amount of reading on pointers to classes but don't get what ive done wrong.


What you had in your last post was a way of putting valid data into the pointers. However from the way you worded it, your original code didn't do that? So the pointer existed but was not initialized to anything valid.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon


I am new to cpp and think that my understanding of pointers to classes is completely wrong.


Let me try to explain pointers this way ...

Say you live at 15 High Street, Newtown.  Now if I write that address down on a bit of paper that is a "pointer to" the house (you might say it is the "address of" the house). But the address isn't the house. Many people could write the address down, but they wouldn't own the house.

Now say up the road at 20 High Street is an empty block. No house, nothing. You could write down the address "20 High Street, Newtown" but it would be an "invalid address". That is, it doesn't "point to" a house. So operations on that address, like "visit the occupants" or "clean the windows" would fail, because there is no house there.

In programming pointers are like that. They are the address of something. And that "something" has to independently exist. A convention in C is to use the special pointer called NULL to represent "a pointer to nothing" (a pointer that doesn't exist yet).

The two ways you generally get a pointer are:


  • Memory allocation (eg. malloc) to get a piece of memory which you can use

  • Allocate the thing statically and then "take its address" with the "&" operator.



For C++ classes however doing a malloc doesn't correctly create the object, because it doesn't call the class's constructor, nor the constructor of any objects inside the class (eg. String objects). So for C++ objects you need to use "new". The operator "new" is not supplied by default with the Arduino environment although it is easy enough to create it.

Unless you have a pressing need to use pointers, particularly if you are not that familiar with them, I would stick to statically allocated objects (eg. put the class in global scope as I mentioned above).
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

howroyd

Nick, thank you very much!

I understood pointers to variables but not classes or functions.  Makes a lot more sense now.  I didn't know you could declare a class outside a function either.  It's still throwing me not having a .h file, which you probably can do but is more hassle than it's worth on the arduino ide.

Cheers!

PaulS

Quote
I didn't know you could declare a class outside a function either.

You have to declare and define the class outside of any function. You can create an instance of the class outside of a function, as a global value. Just to keep the terminology straight(er).

Quote
It's still throwing me not having a .h file, which you probably can do but is more hassle than it's worth on the arduino ide.

It's hard to believe that clicking the button on the tab line, selecting the New Tab menu item, and keying in a name is all that hard.
The art of getting good answers lies in asking good questions.

howroyd

#28
Nov 17, 2011, 11:58 am Last Edit: Nov 17, 2011, 12:14 pm by howroyd Reason: 1
Hmm, I tried that thinking it has to be easy and it was having none of it, saying it couldnt find any classes or functions in a different tab.  Do you have to #include or is that done automatically since it's in the same sketch?

I need more coffee, too many silly mistakes, although I've only been using cpp for two weeks and arduino for 2 days!

I think im preferring arduino to pic33's already!

EDIT:
Just tried using tabs, putting my Adc class in a tab, as suspected it goes nuts lol.  I tried #include<ADC.pde> which is there in the same folder but I still get a compile error:

Code: [Select]
#include <Wire.h>
#include <ADC.pde>

  CAdc          myAdc;                  // Construct the ADC class
  //CAdc         *pMyAdc     = &myAdc;
  CHcontroller  hControl;               // Construct the H2 flow control class
  //CHcontroller *pHControl  = &hControl;
  CTime         myTime;                 // Construct the Time class
  //CTime        *pMyTime    = &myTime;


void setup()
{
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
  analogReference(EXTERNAL);    // Use analogue reference pin (3v3)
  Wire.begin(ID);
  Wire.onReceive(receiveEvent); // register event
  Wire.onRequest(requestEvent); // register event
  Serial.begin(115200);
}

void loop()
{


#ifdef data
  pDummyData = dummyData;
#endif

  while(true){...............................



Quote
pointers.cpp:2:19: error: ADC.pde: No such file or directory
pointers:194: error: 'CAdc' does not name a type
pointers:195: error: expected constructor, destructor, or type conversion before '*' token
pointers.cpp: In function 'void loop()':
pointers:226: error: 'pMyAdc' was not declared in this scope

PaulS

Quote
Do you have to #include

Of course you do. The code is not in the same file. The only way that the compiler knows anything exists is if it referenced in the sketch.

Code: [Select]
#include <ADC.pde>
WTF? The class definition goes in a .h file.

The C in a class name is a Microsoft convention. Absolutely no one else in the world uses it. You do well not to, too.
The art of getting good answers lies in asking good questions.

Go Up