How to start designing your program

Hello everyone,

I just signed up for the forum because I wanted to ask how people start working out the design of their program.

How do you know what functions you need to write and how to setup the variables/constants (global or not) and what to put in a library.

I just started on a timer for a specific competition that has different rounds and different parameters for each round (different distances and locations) and each one has a startsignal and a longer length stopsignal.

I have a basic working program thanks to u8glib and m2tklib (using a small oled as display) and the timing is now taken care of with a state machine that has the different stages of a round:

  • - starting a timer (I am comparing millis() with a stored millies() value to see how much time has past)stopped.
  • - delay after the user presses start
  • - starting of the start-signal
  • - stopping of the star-tsignal after a certain time
  • - starting the stop-signal
  • - stopping the stop-signal and set a variable to let the loop know the timer has

I know the basics of programming, but things like pointers are still a mystery to me (although I understand WHAT they do, I don't understand when to use them), and I feel I could do better if I had a good/better design (for example using timers).

Right now I am having difficulties figuring out how to add the extra functionality that I want and it is because I don't have a good design and don't know how to get everything organised.

Things I want to add:

  • store different configurations in EEPROM. I am thinking about using structs. But having difficulties
  • make a menu where you can configure which configuration is active and edit the configuration/enable wireless/enable external connection to speaker instead of internal one etch.
  • adding wireless, so you can set 1 unit to "slave" mode so you can have a remote signal for a big timer display and external horn. (Can u8g/m2tklib work with another device on the SPI bus?)
  • display elapsed time big on the screen together with a stop button
  • adding an icon if wireless is enabled, in the corner of the screen. (this should be as simple as checking if wireless is enabled in the config and adding that check to a draw() function in the pictureloop that I have for m2tklib)
  • Add a battery indicator, I have ordered a MAX17043 lipo fuel gauge

I am not lazy and eager to learn, but I need a good design to get the mess that I have right now organised and I don't know where to start.

Any help is much apreciated

I can't see a specific question and I'm not clear about your level of expertise.

You may get some ideas from Planning and Implementing a Program

I don't know why you mention pointers. If you know what they are for then you may have come to the conclusion that they could be useful to you. However I suspect they are not needed in most Arduino programs.

For all the things you want to add I suggest you write a short program to learn how to do each thing on its own.

Then if you have a problem and a specific question you will have a short piece of code that makes it much easier to help you.

...R

store different configurations in EEPROM. I am thinking about using structs. But having difficulties

Not helpful in any way. Difficulties how, exactly?

Can't spell "struct" consistently? Have already written to EEPROM so many times already that it is broken?

Robin2: I can't see a specific question and I'm not clear about your level of expertise.

You may get some ideas from Planning and Implementing a Program

I don't know why you mention pointers. If you know what they are for then you may have come to the conclusion that they could be useful to you. However I suspect they are not needed in most Arduino programs.

For all the things you want to add I suggest you write a short program to learn how to do each thing on its own.

Then if you have a problem and a specific question you will have a short piece of code that makes it much easier to help you.

...R

The openingpost of that thread was precisely what I was thinking before I posted this. I will read it and if have a more specific question I will post it here.

Thank you for the pointer :)

AWOL: Not helpful in any way. Difficulties how, exactly?

Can't spell "struct" consistently? Have already written to EEPROM so many times already that it is broken?

For a mod I expected a friendlier reply.

I know how to spell struct consistently, I want to use multple struct.

And no the EEPROM is not broken yet (I may do that in the future ;))

Problems as in how to handle the reading and writing eficciently and how to store everything.

for example, there is no boolean, boolean's take up 1 byte instead of 1 bit so how can I store different settings in 1 byte (wireless on/off, wireless power high/med/low, turn on/off external trigger output etc. all those can be stored in 1 byte instead of 3)

I just signed up for the forum because I wanted to ask how people start working out the design of their program.

Some people start with a [u]flowchart[/u]. I haven't used a flowchart for a long time, and it might not be that useful for "random action" Windows programs. It doesn't make sense to make a flowchart if the program is super-simple and you can imagine the flow in your head.

I think you've got a good start with you list of things your program needs to do. That's where I usually start. Whether you are making a flowchart or not, you need a list of features/functions.

Usually, I'll convert that "list" into program comments or comments as (informal) psudocode, and then I'll replace those comments with the actual code (small bits at a time).

Before you go too far, investigate your hardware requirements. Study datasheets, etc., and figure out what interfaces directly with the Arduino, and what hardware will need additional driver circuits, etc. Count the number of inputs/outputs required and think about assigning I/O pins.

Then (after you have the hardware) start with something simple on the input or output. Or, you might what to start with something hard... If there's something that you think may not work or something that you think is too hard, you might want to start with that before you get halfway through your project and discover your project is not feasible.

In any case, take one small step at a time.

For example, I've done a few sound-activated lighting projects. I usually start by building the analog-input circuit. I read values from the ADC, and send them out to the serial monitor. Once that is working, I'll switch to the lighting-output side. I'll start a new test-development program to make sure I can control the lights under software control before doing anything with the analog input. Then, I'll put the two together with some kind of logic, depending on what kind of effects I want. Again, I'll start with a simple effect that turns the lights on when a certain threshold is hit.

The logic that connects the input & output is the "meat" of your program, and it may be many functions and hundreds of lines of code. Just take it a few lines at a time...

You've already got your OLED working, and maybe some timers, so you've already got a good start.

I've been writing computer programs in various languages for many years, but I don't do it every day and I'm not an expert programmer. So, I usually try to write, compile, and test, one or two lines of code at a time. That's not always an easy thing to do because the program has to "make sense" to the compiler, so you can't just start at the top and work down... If you delete the bottom half of your program, it won't compile.

When I'm making a loop or a function, I'll usually start with a "do nothing" loop/function (or maybe a loop that counts) and I'll send a message out to the serial monitor to confirm I'm in the loop or function. Then, Ill start adding (and testing) "real code" a few lines at a time until the loop/function does everything it's supposed to do.

It's helpful to make use of the serial monitor. You can "print-out" variable-values, or little messages like "Now Writing EEPROM", to make sure the program is doing (or at least trying to do) what you expect.

How do you know what functions you need to write and how to setup the variables/constants (global or not) and what to put in a library.

There is sort-of a general rule to make a function whenever you are doing something more than once. That is, if you find yourself repeating code (or very similar code), you should use a function. And sometimes, it just makes your main loop easier to understand, and it can make your code easier to debug & modify because you are working with smaller chunks of code.

So far, I haven't written a library for the Arduino, but I have thought about creating separate files for my functions. With many-many functions in the same file as the main program, it can be a pain just to find the function if I want to make a change. It would be easier and more organized to open and edit the file with the one function. And if the functions are related, it might make sense to make a library.

There's also a "rule" in C/C++ to avoid global variables. But I'm not following that rule... Probably 90% of my variables are global. That rule may not be as important in "contained" microcontroller programming as with general purpose computer programming, but that's a question for the experts.

When trying to avoid Global variables, I found myself passing a bunch of pointers (or a big structure of pointers) into my functions and it was getting very complicated... So I decided to "cheat". :D

Otherwise, I haven't used pointers with the Arduino, except with arrays (where you can be using pointers without realizing it). You'll probably know if/when you need a pointer. In C++ (but not in C) you can often use a [u]reference[/u] instead of a pointer, and that's a lot easier.

Thank you so much for your tips DVDdoug.

As you mentioned I have a working basic timer with selection of which round you want to time already working with oled display and input controls. But I realised that having a global design before implementing the rest is easier to do since everything can start to become a bit messy.

I think the thread Robin2 posted and your tips can help me a great deal in that! Thanks

One useful method is called "top down design". You appear to be starting on this. Basically you write the main loop of the program first, which calls empty functions. Then you start filling in the functions. At all times you have a valid program which will compile and run but it just doesn't do everything yet.

Displays are hard. Don't start with the display, unless you just put some basic data there and you plan to come back later and make it look pretty. Menus are even harder. Write the menu function last as it is highly dependent on design changes you make and you can get the program mostly working without the menu.

The loop function suggested by Robin in his excellent thread is a good place to start. For this specific program, it could be modified a little:

void setup(){
  loadConfig();
}
void loop() {
  doMenu();
  if(ConfigChanged) saveConfig(); else loadConfig();
  if(IsSlave) doSlaveAction();
  updateDisplay();
}

If you just write some empty function bodies for the functions I suggested above, this will compile and run. Then you can get started implementing the details inside each function.