Let's Make Robots!

A quick programming tip. (Not to step on isotope's feet)

Saves time and avoids many related coding mistakes.

I have been learning about programming for years. More recently, I have been taught that magic numbers or constants should not be hard coded deep in your program. Doing a search for constants magic numbers really only gave me this. Since joining this site I have seen/read about some examples of less than desirable code.

An example would be that you need PI in your code and you need it to a specific decimal place, 3.1415.

Less desirable practice:

wheelDiameter = 2 * radius * 3.1415

...more code

circumference = 2 * circleRadius * 3.1415

More desirable practice

'near beginning of code

PI = 3.1415

wheelDiameter = 2 * radius * PI

...more code

circumference = 2 * circleRadius * PI

With the more desirable practice, if you change your mind on how exact PI needs to be you change the variable/constant in one place and all of your code uses the new number. Otherwise, you must sift through your code and replace every instance with the correct number, correct meaning that if your code is large enough you might miss a replacement or mistype the number.

Another example would be line following. Say you have 3 sensors and they give you a 1 when the sensor is over a white stripe.

Less desirable:

if (sensor1 == 1 and sensor 2 == 1) then veer left;

More desirable:

left = 0b100 'binary representation of sensors white on black

'left = 0b011 'black on white

leftCenter = 0b110

... more code

if leftCenter then veer left;

Now, if the conditions change and you are instead looking for a black line on a white background you need only change a batch of constants at or near the beginning of your program. You could even code them in as remarks.

I hope this helps someone. I will accept any and all criticism.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I've never had formal training in programming and this kind of stuff is gold.

I really have no sweet tips (I'm looking to get some!) but would like to add something instead of just giving a sincere \o/ I would like to promote this PICAXE programmer tip for collapsing code blocks, courtesy of fritsl! Manage your subroutines with style. It also feels natural for those already adept in C.

Keep it comin!

With picaxe you can also use simple calculations in the constants/symbols. No extreme formula's but you can make good use of this.

In one of my programs I kept changing the frequency the CPU was running at and with picaxe, that means that you have to change the length of the pause commands and a few other commands. To help me with that I define a pause_factor and a few standard pause lengths.

Since all these are symbols they dont take up extra programming space.All calculations of the symbols is done at compile time.

This way; you only have to change one symbol to get all the others recalculated

I've always been better at hardware than software but since discovering that the Arduino IDE allowed you to use multiple tabs I have always defined my I/O pins in an "IO_pins" tab and my constants in a "Constants" tab.

This makes it so much simpler when you want to change an I/O pin or adjust a servo center position value. Although these definitions can be just put into the program it is much quicker with large programs to switch between tabs rather than scrolling up and down through your code.

A good example is the sample code I posted for "Chopsticks"

If I ever decide to try arduino, I will hope to remember this. If I don't, I hope some of the many other builders here find your input useful.

More instruction on programming do's and dont's is always a good thing.

In fact this is programming 101 -- or is that "programming 5" :-) -- define constants for never-changing values, and define these in an easily maintainable place.

Unsure what language you use though?

With C (and dialects) I usually include a config.h which has project constants and other useful macro's defined. I would even go this far:

#define PI  3.1415

#define RAD2CIRC(radius)   (PI*radius*2)

#define DIA2CIRC(diam)    (diam*PI)

But that example does not fully demonstrate /why/: I do it because it's less to type and it's easier on my eyes that don't like seeing duplicate code all over the place. (I guess, R2C and D2C would be what I'd use in practice)

BTW, in C, there's the M_PI constant defined in math.h; but still it can be faster to bake, erm, define your own pi with lesser digits (it seems logical that a multiplication with a number of lesser accuracy is quicker (and the result can be more than precise enough) although the gain in calculation-time may be completely unnoticable).

And yep, defining your bitmasks as constants is also very useful, think of, for instance, bump-detection.

#define FRONT_LEFT_COLLISION 0b01

#define FRONT_RIGHT_COLLISION 0b10

#define FRONT_FULL_COLLISION 0b11

Imagine a big robot with lots of sensors. Using those constants makes the code more readable -- having the 0bXXXX values in your code makes typos hard to catch, especially at 1:30 AM.

Also, once you decide to put an extra sensor at the front, only a slight adjustment needs to be made:

#define FRONT_CENTER_COLLISION    0b100  /* the new sensor */

#define FRONT_FULL_COLLISION    0b111

The full frontal collision will be handled fine in the re-compiled program.

(In practice, that new pin could be the 6th bit -- its actual value being 0b100000. Or you decide to rewire stuff. Apart from redefining these values the core code doesn't need any change because it works with those wisely defined constants.)

Hope this helps someone too. :)

I hope you don't mind me adding my two cents (even though you and Birdmum got the point through pretty thoroughly)...

I personally like to define all my pins with names:

#define FRONT_SENSOR   0b100

Then define the collision with the pins and the bitwise or operator:

#define FRONT_CENTER_COLLISION   FRONT_SENSOR | LEFT_SENSOR | RIGHT_SENSOR

this way if you need to change a pin you can change the single #define FRONT_SENSOR value instead of all the #define COLLISION values

Its basically a reiteration of what has already been stated.

cheers

I was truly hoping for this kind of response. As, I was sure I would not explain it completely or completely accurately. :)

The PI example was weak, as like you mentioned it is most likely a constant in a file that can be included somewhere. I just couldn't think of anything right off the top of my head.

Yeah, I figured that the pi-thing was just to illustrate an example use. Everybody knows circles so it's a good pick :)

Not Hard coding always helps in better readability and easy maintainance. Thanks for tips birdmun.

Whenever I write code, I normally always try to define it and then use it unless I am experimenting.