Using functions in your code

This is for beginners. If you are an advanced programmer, you can skip this post 🙂

If you perform a common task in several parts of your program, instead of repeating the code several times in your code, you make that task a function to call.

Say if that common task is to play a Happy Birthday tune, which involves various tones and pauses, then you can define a function to do that.

void sing_happy_bday()

{

}

Now say some of your tasks involve playing this tune and other stuff, you can use a switch-case structure:

#define over_phone 1

#define home_visit 2

#define restaurant_celebration 3

int mode=over_phone;

void celebrate_bday()

{

  switch (mode)

  {

     case over_phone:

     call_bday_mom();

     chat();

     sing_happy_bday();

     hang_up();

     break;

     case home_visit:

     knock_on_door();

     hug();

     light_candle();

     sing_happy_bday();

     hug();

     say_bye();

     break;

     case restaurant_celebration:

     drive_to_restaurant();

     wait_mom();

     hug();

     order_bday_cake();

     light_candle();

     sing_happy_bday();

     hug();

     pay();

     exit_restaurant();

     break;

  }

}

 

In the above pseudo code, there are multiple functions that are called more than once, such as hug(), light_candle(), sing_happy_bday(). They are the smallest functional modules that are used many times in various parts of the code. Making them into functions makes the code easier to understand and avoid repeating code, which wastes memory space. Also, if you want to change how sing_happy_bday() is implemented, say from just singing into singing with a guitar, all you need to do is to change the sing_happy_bday() function. If you didn’t turn this module into function and repeated it several times in your code, you will need to modify several places to add the guitar. Mistakes happen when you have to modify several places. Maybe in a rare case, you will sing without the guitar, surprising the bday girl 🙂

Benefits of making modules into functions:

*No repeating code so saves memory

*Easy to modify code since the code only has one copy

*Program is easy to understand than packets of details

Drawbacks:

*Program runs slightly slowly (you won’t notice) since a jump is needed to get to the function and a jump is needed to return from the function

*I want to say more but came up short. Rarely do you need to think of the drawbacks 😉

sprintf

I notice that lots of arduino fans are not coming from a C programming background. Even the C++ people may not know such a neat C feature, the sprintf function. I use it so often in my codes and libraries thus it demands a small introduction.

The following is a link to the sprintf function (I’ll be adding this link to my sample codes):
http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

Essentially the sprintf function takes in a few parameters, such as integers, floats etc. and then follow a format string, output a formatted string that involves the parameters. Since arduino doesn’t print float (to reduce compiled file size), you may need to print two integers for a float. Say if I want to print on LCD the current time in the following format:

13:02:00

I have three variables:

int hour=13;
 int min=2;
 int sec=0;

If I do the simple print, I have to do the following:

 lcd.print(hour);
 lcd.print(":");
 lcd.print(min);
 lcd.print(":");
 lcd.print(sec);

And the result is less than perfect:
13:2:0

So how do I demand the formatting of the numbers to have a maximal 2 integer digits and no missing leading zeros? I have to tell the print function so by means of a format string. Let’s start from simple and add all details step-by-step:

A format string is just a string.
First I want to output integer (not float or else), so integer output is “%d”, or “%ld” for long integer.
Next I want 2 digit integer so “%2d”, or “%4d” if I wanted 4 digit integer.
Next I want to keep leading zero so my time looks right, so”%02d”. If I used “%2d” then leading spaces are provided so I get 13:(space)2:(space)0

Now I’m done with format string, it’s time to call the sprintf:

char[9] buffer=""; ///< This is the buffer for the string the sprintf outputs to
sprintf(buffer, "%02d:%02d:%02d", hour, min, sec); ///< This has 3 2-digit integers with leading zeros, separated by ":" . The list of parameters, hour, min, sec, provides the numbers the sprintf prints out with.
lcd.print(buffer); ///< You will get "13:02:00"

This will get you:

13:02:00

From the above example you can see that you can mix regular texts such as “:” or else with the format string in a complex output. Say we want to output a count-down number like “You have XX minutes left.”, then we do:

sprintf(buffer, "You have %2d minutes left.", min);

You always need to have a buffer char array long enough to hold the output. Count the characters before you define the length of the buffer array and add 1 to the count for string terminator. For the above string, the output is 25 characters, the “%2d” counts as 2 characters. Then you do:

char [26] buffer="";

It’s worth mentioning that sprintf is just for the look. There is no reason to use it if you don’t care about the look of your output.

Now that you have read so much about sprintf, you may also want to know sscanf, which is the opposite. It picks out number from a complex string so if you have a string like “13:02:00”, you can extract hour, min, and sec from the string. This is especially useful when accepting parameters from serial port. If you want to know about this function, read here or reply to this post saying you are interested in a post about the sscanf.

http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/

How to update codes and libraries for arduino 1.0

The arduino 1.0 IDE (integrated development environment), or the arduino software 1.0 has been released for a while now. Some of us are moving slowly to adopt it since all codes and contributed libraries (yeah that includes all my open-source libraries, darn) will have to be modified to run on the new environment. Here is a great article on how to make the change:

http://blog.makezine.com/archive/2011/12/arduino-1-0-is-out-heres-what-you-need-to-know.html

Besides the above article, here are some more subtle changes you have to make in order to get on board with the new IDE:

  1. Any time you have a hardware serial write command with zero as argument such as Serial.write(0) or Serial.write(‘\ 0’), you will have to replace them with the following: Serial.write((uint8_t)0). The reason behind this is that in the new Print class, which Serial class inherits from, the write(char*) method is no longer virtual but actually defined. This write(char*) method and the write(uint8_t) method are both non-virtual and become ambiguous when the argument is zero. The zero could mean zero BYTE value or zero pointer to char array, which is allowed (no other constant values are allowed as pointer). To clear it up, you force the zero into BYTE, or the unsigned 8-bit integer type: uint8_t
  2. Any other libraries that derive from the Print class will have the same issues. You have to do the above regarding to write(0).
  3. I’ll add more when I find more updates.

If you are using the New Soft Serial, then I recommend the following change: don’t make any changes and stay with arduino 0022. I have been unable to access the website that hosts the New Soft Serial library and I don’t think the library has been modified for arduino 1.0 yet. I’ll have to wait and see if anything further happens to this library, which I really like.

The NewSoftSerial is actually turned into the official SoftSerial, released with arduino 1.0 so all you have to do is to include the SoftSerial library.

Rotary encoder

A rotary encoder is a digital device in the shape of a knob. You can turn it in either clockwise direction or counter-clockwise direction infinite turns, without any limit. This is what a potentiometer can’t do. In the old days most knobs are potentiometers or rotary switches, such as those on stove top, washers and dryers. Potentiometer is much easier in the concept to sense than a rotary encoder so here we discuss how to sense a digital rotary encoder.

How does it work?

A simple rotary encoder has two channels or switches. If you turn the encoder’s shaft, the two switches will open and close repeatedly much like two tactile buttons. Depending on the direction of the rotation, the sequence of the open and close will be different. Say we have two channels A and B that open and close as we turn the encoder and if we turn the encoder clockwise, we will see:

A open->B open->A close->B close

If we turn counter clockwise, we see:

B open->A open->B close->A close

So to tell which way the encoder is turning, we just need to tell which sequence occurs. There are many ways to tell which sequence occurs but I will focus on the easiest way, which is also efficient enough.

First, you combine the status of the switches A and B into a 2-bit binary number, A being the low bit and B being the high bit. Let’s define open as 1, and close as 0. Here is how to combine the status bits:

stat=(digitalRead(EncoderChnB)*2) + digitalRead(EncoderChnA);

When both channels are closed, we get 0. When both are open, we get 3. When only a is open, we get 1. When only b is open, we get 2.

Now we can translate the sequences into numbers:

A open->B open->A close->B close ==>> 1,3,2,0

B open->A open->B close->A close ==>> 2,3,1,0

Note that in the first sequence when B opens after A opens, they are both open, so that corresponds to 3.

Now we can make an array to store both sequences with a pointer:

byte stat_seq[]={0,1,3,2,0,1,3,2,0};

byte stat_seq_ptr=4;

The pointer initially points to a status of both switches closes, which is a detent position for the encoder. You turn your encoder and it clicks into detent positions. If your detent position is when both switches are open, you may use {3,2,0,1,3,2,0,1,3} instead.

Now, every time you read the two channels, you compare the stat with the array element before and after the current pointer’s position. If the stat represent the array element after the current pointer, move the pointer there, same for the other way around. When the array pointer hits the left end of the array, with a 0, you have completed one CCW turn, report this turn and reset the pointer to the middle, 4. Same for CW turn when the pointer reaches the right end of the array.

This should be easier to understand than other ways of tracking the encoder and is much more robust. Here is the complete code:

The function returns the number of CW or CCW turns stored in its buffer. Every time you call it to ask number of CW turns, it returns the turns and decrements its internal count by one. All you need to do is to keep calling this function every loop by supplying which direction you want to read back. If the read back is greater than zero, a turn is made by the user. You can decide what to do, maybe advance in a menu. If the return is zero, there is no turn in that direction, you need to do nothing. The green section is sensing the encoder and the blue section is responding the the caller.

byte read_encoder(byte direction) // 1 for asking CW counts, -1 for asking CCW counts. Returns counts and decrements the counts till 0.
{
  static byte stat_seq[]={3,2,0,1,3,2,0,1,3}; // For always on switches use {0,1,3,2,0,1,3,2,0};
  static byte stat_seq_ptr=4;
  static byte cw_counter=0;
  static byte ccw_counter=0;

  byte stat_int=(digitalRead(EncoderChnB)<<1) | digitalRead(EncoderChnA);
  if (stat_int==stat_seq[stat_seq_ptr+1])
  {
    stat_seq_ptr++;
    if (stat_seq_ptr==8)
    {
      stat_seq_ptr=4;
      cw_counter++;
    }
  }
  else if (stat_int==stat_seq[stat_seq_ptr-1])
  {
    stat_seq_ptr–;
    if (stat_seq_ptr==0)
    {
      stat_seq_ptr=4;
      ccw_counter++;
    }
  }
if (direction==1)
  {
    if (cw_counter>0)
    {
      cw_counter–;
      return cw_counter+1;
    }
    else return 0;
  }

  else if (direction==255)
  {
    if (ccw_counter>0)
    {
      ccw_counter–;
      return ccw_counter+1;
    }
    else return 0;
  }

  else return 0;
}

A new design phi-panel

I am working on a panel that a microcontroller like arduino or even PIC or a PC (via USB TTL adapter) will be able to talk to over serial. Just imagine the old computer terminal with a display and a keyboard, that is what this panel is trying to mimic. The arduino sends out strings to display on the LCD and the panel displays it with line wrap and auto scroll. Arduino is also able to control the position of the cursor and brightness of the back light like serial LCDs besides basic printing. It also sends key presses to arduino for processing. A beginner without programming skills necessary to write a button code or understanding of how to hook up an LCD or matrix keypad can simply leap from the arduino serial.print examples of printing to serial window to displaying on the LCD and processing key presses. If a user presses the zero (0) key on the panel, arduino will receive ‘0’ in the serial port so the simplest interaction could be this simple:

Serial.print(“Menu\n1.Start motor\n2.Stop motor\n3.Set speed); // The ‘\n’ represents new line so the menu is displayed on 4 rows of a 20X4 display

while(1)

{

if (Serial.available())

{

char response=Serial.read();

if (response==’1′) move_motor(); // Do stuff to move the motor

if (response==’2′) stop_motor(); // Do stuff to stop the motor

if (response==’3′) set_speed(); // Do stuff to change motor speed setting

}

}

To be honest, I think this is an awesome project that will empower electronics beginners like what arduino did to all of us. Just think about it, who else can make a menu this quick and easy before?

 

I’ll post more info once I get the PCBs and finish my software.

Project code updates

Since I have updated my phi_prompt library, some of my project codes stopped working due to the library update. I’ve made changes to some of them to get them up to date and still have to update several more. So I decided to make a chart to show how my various libraries are related so that if I update one library, what else I need to update in order to make all my codes work.

Here is the chart. It’s too big to fit in the blog so feel free to click on it to show the whole image.

This also shows some planned updates such as adding functions in the I/O layer to make the user interface access more types of switches such as keypads with column/row pins, IR remote keys on an IR remote, PS2 keyboard, etc, and also in the system layer such as porting the phi_prompt library to graphic lcds (must be lots of work). Also the library versions are included so that you can check your folders to make sure the correct versions are there to support your applications.

Organize your code – big ASCII art font

I have written several post on how to optimize your code, specifically optimizing memory usage, and keep them in separate tabs to organize a longer project. This time it is a trick I do (didn’t see anyone else I know do this yet). In Arduino, you can create block comments as the following:

/*

All is comment

blah….

*/

So besides using these block comments to document how to call a function you wrote or how to configure a library or else you can also do the following:

/*
.___  ___.  _______ .__   __.  __    __
|   \/   | |   ____||  \ |  | |  |  |  |
|  \  /  | |  |__   |   \|  | |  |  |  |
|  |\/|  | |   __|  |  . `  | |  |  |  |
|  |  |  | |  |____ |  |\   | |  `--'  |
|__|  |__| |_______||__| \__|  \______/
*/

Pretty cool, right? It clearly indicates the content after this comment has something to do with menu. If you scroll through your hundreds of lines of code, this will catch your eyes much easier than any comments. Although some programmers use a row of # or – to separate codes, this is better. you can have all of these elements together to improve the overall readability of your code:

/*
########################################
.___  ___.  _______ .__   __.  __    __
|   \/   | |   ____||  \ |  | |  |  |  |
|  \  /  | |  |__   |   \|  | |  |  |  |
|  |\/|  | |   __|  |  . `  | |  |  |  |
|  |  |  | |  |____ |  |\   | |  `--'  |
|__|  |__| |_______||__| \__|  \______/
########################################
Menu functions go here!
*/

Here is where I found this starwars font:

http://www.network-science.de/ascii/

Just scroll down the font list and find your favorite!

To read all my posts on coding, press the “coding” button on my blog.

Oh here, someone made a movie with ascii art:

http://www.asciimation.co.nz/

Password panel

Password panel for Arduino Phi-1 shield

introduction:

I have been thinking about this for a while: an arduino password input panel. You will be prompted to enter a password, you have three trials. If you pass, something happens, if you fail, something else happens. You decide!

After I recently pre-released the phi-menu, a versatile arduino shell for interacting with users and building menus, I realized I could make the password panel very easily with ph1-menu.

The project simply calls input_panel2() to get a string from the user, 6 digits long, ‘0’ to ‘9’ (you can change this yourself). Then it compares the user input with the stored password. If it is correct, it returns true and prints some good texts. If it is incorrect, the user is given more trials until the trials run out and some not so good texts are shown.

A second part of the project is a function that updates the password to different numbers and updates number of trials a user can have. This part, ideally only gets called after authentication, will be a part that you can offer to authenticated users. I’m just having it here as a demonstration of how easy it is to make something out of phi-menu.

Here is a video:

Here is the code:

Full version with Phi-menu

Nutshell version (password is, well, read my code!)

About phi-menu

Please refer to the phi-menu page for all the details

Optimizing your program

The following is just a reply I made on arduino forum. May be useful to share.

This is related to another post a while ago:

https://liudr.wordpress.com/2011/02/04/how-to-optimize-your-arduino-memory-usage/

In case you run into memory issues,

On the efficiency in function calling:
1) Stack space is filled with return address and parameters you pass to your function
2) Your function may need to establish new variables costing more memory
3) You can rewrite the layers of functions, combining some layers if the lower layer doesn’t ever get called by more than one caller.
4) Using global variables reduces parameters passing to your functions, but also reduces readability re-usability of your code. Say you have one global msg[] for printing messages for serial or lcd and any function uses that array.

Other issues:
1) do you have too many strings? (move them to FLASH with PROGMEM)
2) have you defined too many variables that don’t ever change? (replace with #define)
3) are you using float where a short will suffice? (reduce footprint of each variable)
4) are you using too many overloaded versions of one library function? Say you use lcd.print(int) and lcd.print(string) and lcd.print(float). Try use only lcd.print(string) and use sprintf for formatting since it’s the best way ever.

Using tabs in Arduino IDE

If you plan to write a moderate to long program in Arduino IDE, you should learn to use tabs to keep your codes organized. Let’s talk about this issue in some details.

First, you should have a plan, what kind of problem you are trying to solve with your program, how you will solve it. But most of the time we only had a rough idea what we are going to do and as we are doing it our programs grow bigger and messier. OK, if you follow my suggestions on how to use tabs (i.e. separate your one giant file into several smaller files), you will survive:

You should try to cut your program into smaller pieces, so that each piece represents a specific set of functions. Say you have a sonic ranger in your setup. Then you will likely have sonic ranger reading functions, displaying distance from reading, displaying speed from distance readings. These functions are better off separated from those that read and display value from a temperature sensor.

You can keep all these pieces in your main program file but soon your main program becomes too long and you find yourself scrolling the side bar up and down, looking for one bit of program to modify.

Here is how to separate your program into several pieces, each having its own file name.

  1. Press this button to drop down a menu, then select new tab.
  2. On the bottom of the arduino IDE window, type a name descriptive enough, like measure for all your sensor measurement functions.
  3. Cut your sensor measurement functions from your main program, and paste them in the newly created file, which is now a tab inside arduino IDE.
  4. To make matter even more clear, add several lines of comment describing what these functions do. This also helps you organize your functions.

Here is an explanation of what you have just done: if you write codes in separate .pde files, you need not worry anything regarding whether one function in one file knows the other functions defined in other files as all .pde files are concatenated into one file before arduino IDE compiles everything so it the same as writing all those lines of code in one file, just more organized.

Essentially, you should only keep all variable definitions, setup() and loop() in your main .pde file, and disperse all your functions into their separate .pde files, like this one in picture.

Starting here, you will have to seriously programmed for quite some time to hit another road block to need my following help:

Say you have succeeded in creating many hundred lines of code. You have also come to understand the importance of using #define and PROGMEM. The head of your main .pde becomes annoyingly long like this but only more lines:

#ifdef stand-alone
// Stand-alone photogate setting
#define button1_pin 11 //enter
#define button2_pin 13 //down pause
#define button3_pin 12 //up unpause
#define button4_pin 10 //Escape
#define gate0_pin 15
#define gate1_pin 14
#define gate2_pin 17
#define gate3_pin 16
#endif

#ifdef shield
// Photogate shield setting
#define button1_pin 12
#define button2_pin 11
#define button3_pin 10
#define gate0_pin 3
#define gate1_pin 2
#endif

#define pulley_spokes 10 //16 spokes are evenly laid on the pulley.
#define storage_size 100
#define rotation_update_time 1000000
#define two_pi 6.2831853
//#define vol_a_val (10.0000/1024.0000) // This maps -5V to +5V into 0-5V with a bipolar to unipolar converter.
//#define vol_b_val (-5.0000)
#define vol_a_val (5.0000/1024.0000) // This is the default mapping for internal AD converter.
#define vol_b_val (0.0000)

Now you are contemplating on adding just another tab, called includes.pde

In that tab you type : #define haha 7

In your main program you have int data=haha;

You compile, and an error pops up:

What the ?$%^& You defined haha but the IDE fails to recognize it? You quit coding and go on and forget arduino all together. Maybe you should read on for the source of the error instead:

First do int data=7; so you can complete the compile. Then take a look at the temporary file arduino IDE generated under:

C:\Users\owner\AppData\Local\Temp\

Under a folder called build1555865782840320506.tmp or like, you can find all the files generated by arduino IDE while compiling.

You can find more about these files on this blog post: http://smileymicros.com/blog/2011/02/10/where-is-the-arduino-hex-file/

Open that .cpp file that is named the same name as your main .pde file and look in the very end you will find the answer:

#include “WProgram.h”
void setup();
void loop();
int clock = 6; // Define encoder pin A
int data = 7; // Define encoder pin B
int count = 0; // pre-init the count to zero
int c = LOW; // pre-init the state of pin A low
int cLast = LOW; // and make its last val the same – ie no change
int d = LOW; // and make the data val low as well

void setup() {
pinMode (clock,INPUT); // setup the pins as inputs
pinMode (data,INPUT);
Serial.begin (9600); // and give some serial debugging
}

void loop() {
c = digitalRead(clock); // read pin A as clock
d = digitalRead(data); // read pin B as data

if (c != cLast) { // clock pin has changed value… now we can do stuff
d = c^d; // work out direction using an XOR
if ( d ) {
count–; // non-zero is Anti-clockwise
}else{
count++; // zero is therefore anti-clockwise
}
Serial.print (“Jog:: count:”);
Serial.println(count);
cLast = c; // store current clock state for next pass
}
}

#define haha 7

Aha! The content of your includes.pde is concatenated to the END of your main .pde file! Have you heard of “define before use”?

This is what arduino IDE does, it concatenates all .pde files, starting with the main .pde then in alphabetic order. So if you define something in a .pde file or tab, then the definition appears after the main .pde and the defined entity CANNOT be used in main .pde or any other .pde file that is alphabetically ahead of the file that has the definition. DARN IT!

How do you fix that?! Maybe return all the #define lines to the main .pde and curse the arduino IDE and get over with it?! You should simply choose to read on.

To really think out of box, we need to separate those pesky #define lines from our beautiful main .pde, and we need those #define lines to be compiled AHEAD of the main .pde! That is right, AHEAD of the main .pde. You are thinking in the correct direction. To redirect the order in which the compiler compiles, you can use a HEADER file! Have you not programmed in the old-fashioned C? Always have “#include <stdio.h>”? Don’t worry, we’ll get there.

Now let’s change that includes.pde into includes.h

Then in the beginning of your main program, add the following magical line: #include “includes.h”

Then modify your code so again you have int data=haha;

Compile, succeed!

Here is the temporary output file:

#include “includes.h”
#include “WProgram.h”
void setup();
void loop();
int clock = 6; // Define encoder pin A
int data = haha; // Define encoder pin B
int count = 0; // pre-init the count to zero
int c = LOW; // pre-init the state of pin A low
int cLast = LOW; // and make its last val the same – ie no change
int d = LOW; // and make the data val low as well

void setup() {
pinMode (clock,INPUT); // setup the pins as inputs
pinMode (data,INPUT);
Serial.begin (9600); // and give some serial debugging
}

void loop() {
c = digitalRead(clock); // read pin A as clock
d = digitalRead(data); // read pin B as data

if (c != cLast) { // clock pin has changed value… now we can do stuff
d = c^d; // work out direction using an XOR
if ( d ) {
count–; // non-zero is Anti-clockwise
}else{
count++; // zero is therefore anti-clockwise
}
Serial.print (“Jog:: count:”);
Serial.println(count);
cLast = c; // store current clock state for next pass
}
}

Notice the “#define haha 7” line is gone from the end of the temp file. But a line #include “includes.h” appears in the beginning of the file. The function of this include line is to insert the content of the included file i.e. “includes.h” right where the #include line appears in the file. This way, anything you write in the includes.h file appears magically before the main content of your main program, when it compiles.

We call #include a pre-compiler command or directive. It tells the compiler where to locate a file and insert its content at the spots of this very #include command. So if you have

Dear Sir and Madam,

#include <declaration of independence>

Thank you for your attention!

then the entire content of the declaration of independence appears in your speech, whether it’s relevant or not.

Now that you’ve spent so much time reading this post and learned a trick or two, you may want to read on to learn all the tricks.

With #include, we can put all the #define lines in our “includes.h” files, then add #include “includes.h” in the beginning of the main program, tada!

Maybe now you get a bit over confident and start to move variable definitions into includes.h

Sorry to tell you, that won’t work.

This post is already too long and we are wandering off topic. So to continue on the solution to your problem, please read on how I use different files to organize my project. See you on another post!

%d bloggers like this: