robot code going in a good direction..?

I wanted to start learning Arduino, electronics and programming so I’ve built myself a 6 legged, 2 DOF per leg robot incorporating an Arduino Mega 2560, sonar, bluetooth, a piezo speaker and a couple of flashing laser thingies…

After a bit of swearing, it’s doing what I’m after. It’s still very much a ‘growing’ work in progress, but I’m not sure if I’m doing things in a sensible way. :~

Would anyone be kind enough to look over the attached sketch and give any suggestions/comments please?

tia,

'tunes

Plank_0022.zip (8.85 KB)

One thing I would do is write a couple of routines called debugPrint and debugPrintln that take a string as a parameter and test your debug variable to decide whether to send the string passed to serial2. It would simplify your code quite significantly removing all those if(debug) statements and associated braces.

Better, have those routines take a boolean and a string and pass debug or movesDebug so that the routine is provided with the debug control variable it's supposed to test.

wildbill:
One thing I would do is write a couple of routines called debugPrint and debugPrintln that take a string as a parameter and test your debug variable to decide whether to send the string passed to serial2. It would simplify your code quite significantly removing all those if(debug) statements and associated braces.

Better, have those routines take a boolean and a string and pass debug or movesDebug so that the routine is provided with the debug control variable it’s supposed to test.

nice idea wildbill, thanks! i like the idea of different levels of debug messages, so i might try out something like debug (int level, int port, str message). Then I could pass where to debug to as well (usb or BT).
ill get reading on passing strings…

debug(0,2,"bug!");

void debug(int level,int port,String message){
  if(level<=debugLevel){
    if(port=0){									// USB
      Serial.println(message);
    }
    if(port=2){									// BT
      Serial2.println(message);
    }
  }
}

…will pass readable text OK, but I can’t figure out how to get it to print the contents of a function. anyone know how pls?

if(port=2){

Oops

but I can't figure out how to get it to print the contents of a function.

Not sure what you mean there - the contents of a function would be the source code, to which the compiled sketch has no access.

hi awol.

i meant variable, it was getting a bit late.

i'd like to be able to do debug(int level,int port,String message, variable to pass), to produce 'message variable contents' over the right serial port. im not sure how to handle the type of 'variable to pass' though, it could be the contents of any variable...

..and =s are now ==s

thanks

it could be the contents of any variable…

So, don’t do it with a function, do it with a macro, and let the compiler and overloads deal with the data type.

oops. To clarify, I meant string, not String. Use char* as your parameter. Using Strings in arduino code is asking for trouble given the dynamic memory allocation that they bring to your comparatively tiny heap.

sorry AWOL, ive done some googling but 'dont get it'. could you let me know the basics of how please? macros are something i (think) ive not used before.

wildbill, i thought i got that done too easily. ill change it now.

Well, there are a couple of approaches - a purist template:

template <class T> void debug (int level, const char* label, const T& value)
{
  if (level >=DEBUG_LEVEL) {
    Serial.print (label);
    Serial.println value);
  }
}

or the macro

#define debug(level,label,value) do { \
if (level >=DEBUG_LEVEL) { \
    Serial.print (label); \
    Serial.println value); \
  } \
} while (0)

(both should have dummy, empty versions of “debug” with conditional compilation for when you don’t want any debug at all)

(all code uncompiled, and untested. The template version has a reference so will have to go into a separate header file)

i think I like the idea of the macro more, but I can't get it to compile and don't understand it enough to get it going.. I'm just breaking it.

I'd really appreciate any further explanation you could give

   Serial.println (value); \

Missing parenthesis, sorry.

I'm still in the same situation..

I got it to compile once, put saw no serial output from it at all.

atm, I'm getting error: expected unqualified-id before 'do', using

debugg(0,"label",stepDelay);

in my loop

and

#define debugg(level,label,value) do { \
if (level >=DEBUG_LEVEL) { \
    Serial2.print (label); \
    Serial2.println (value); \
  } \
} while (0)

void debugg(int level,char* label,int value){}

(ive renamed it all debugg so it doesnt clash with my current debug setup)

how have I broken it?

Get rid of the function definition:

void debugg(int level,char* label,int value){}

You don't need it.

The macro is your declaration - you don't need the function declaration in this instance.

Remove the "void debugg(int level,char* label,int value){}" and you should be good to go.

All you need is:

#define DEBUG_LEVEL 1
#define DEBUGG(level,label,value) \
if (level >=DEBUG_LEVEL) {\
    Serial2.print (label); \
    Serial2.println (value); \
}\


void setup()
{
 Serial2.begin(9600);
}
void loop()
{
static int x = 0;
//And then to call it:
    DEBUGG(5, "label", x++)
//Note the lack of a  semi-colon here.
delay(100);
}

As a side note, traditionally you would identify macros by keeping the name all uppercase ( ex: DEBUGG ). Otherwise it's easy to forget its a macro and not a function (where you'd need a ; )

The while(0) to force a semi-colon when calling the macro really bothered me. Sorry AWOL!

The do..while is not there to "force a semicolon".

I suppose it depends on your primary platform.

Microsoft's C++ compiler would throw compiler warnings all over the place when you did the #define X do {...}while(0) because by itself, it wasn't valid code. Of course, when you called it via X(); it all worked.

My understanding of the do while(0) macro is sort of a safeguard against poor coding practices where someone would use the macro inside an if statement without braces.

But a large part of the initial push to even use the do while, is that when people declared macros as #define X { a=1;b=2; }, people would forget it was a macro and still call it as X(); which caused compiler errors in if-else statements among other things.

Slightly off topic, but it's an interesting discussion as to the best way to declare multi-line macros... Do yo u write them so they must be treated as a function (and deal with compiler warnings on msft), or do you keep mental notes to not use ;'s on macros.

Personally, I prefer to avoid multiple line macros, and use functions when memory isn't a serious issue.

Thanks tgm1175, that got it going. Seems to handle most things I'll want it to do already too.

The Arduino IDEs Auto Format breaks it though, I've found.

Any other suggestions/comments anyone?

Well if you're using a macro anyway, you can use the stringify and LINE features so that you just say

void setup() {
  int x = 28;
  DEBUG(x);
}

and it will print

x = 24 at line 3

It would look a little like this

#if DEBUG
#define DEBUG(x) do { Serial.print(#x " = "); Serial.print(x); Serial.print(" at line " __LINE__); } while (false)
#else
#define DEBUG(x)
#endif

The major problem with that being that LINE won't work with arduino since it adds a bunch of stuff before it compiles the sketch.

The debug thing's working nicely, thanks everyone.

any more suggestions or comments pls?