Many IF statements alternative

Go To Last Post
64 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Question about writing C code for an arduino atmega328p:

 

How could I simplify this code without using so many if statements? Is there some way to use a look-up-table, or another technique that will speed up the process in a time-sensitive setting?

 

EX:

///////////////////

value = 'f';

 

if (value == 'a')

  do something;

if (value == 'b')

  do something;

if (value == 'c')

  do something;

if (value == 'd')

  do something;

if (value == 'e')

  do something;

if (value == 'f')

  do something;

if (value == 'g')

  do something;

if (value == 'h')

  do something;

//////////////////

 

"value" would be a variable letter that can be 'a' thru 'h'.  

This seems like the quickest way (that I'm aware of), but also seems redundant. I'm new to this so I appreciate the help.

This topic has a solution.
Last Edited: Tue. Jul 24, 2018 - 09:37 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2
switch (value) {
    case 'a': {
        something;
        break;
    }
    case 'b': {
        something;
        break;
    }
    case 'c': {
        something;
        break;
    }
etc.
    default: {
        handle_unexpected_value;
        break;
    }

}

If "something" is real simple then a shortened form:

switch (value) {
    case 'a': something; break;
    case 'b': something; break;
    case 'c': something; break;
etc.
    default: handle_unexpected_value; break;
}

Last Edited: Tue. Jul 24, 2018 - 01:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see that switch statements work much faster than if-else. Thank you!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This only works when comparing a variable to a constant.  When comparing two variables to each other "if-else if-else if-else" is your only choice.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seriously,  you must select your logic for what you want to do e.g.

if (value == 'a')
  do something;
if (value == 'b')
  do something;
...  

is different to

if (value == 'a')
  do something;
else if (value == 'b')
  do something;
else if ...

Using switch-case construct is if ... else if ... else ...

i.e. only one case is executed.

 

People worry about the "look".   Instead you should worry about the "logic"

The Compiler will do an excellent job in translating exactly what you asked it to do.

 

In your situation with multiple "consecutive cases" you will be amazed how well Compilers translate it.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I see that switch statements work much faster than if-else.

Well, no, it doesn't really. It kind of depends how the compiler chooses to implement the swithc() but it'll tend to be a cascading if/else anyway. Of course (assuming your 'value' can only be one of 'a' to 'h' at a time) your original code was wrong anyway. Rather than:

if (value == 'a')
  do something;
if (value == 'b')
  do something;
if (value == 'c')
  do something;
etc.

it should have been:

if (value == 'a')
  do something;
else if (value == 'b')
  do something;
else if (value == 'c')
  do something;
etc.

in which case switch/case is basically just syntactic sugar for the same thing.

 

HOWEVER what the compiler is allowed to do with switch/case (assuming all the cases are adjacent values) is to make a "computed goto" with a dispatch table and using value-'a' as the index into that table.

 

But it will depend on the actual code, the range of case options and even some compiler switches as to when/whether the compiler chooses to do it that way.

 

The advantage of a computed goto is that all paths (whether 'a' .. 'h') all take the same time to execute. Whereas with a cascaded if/else (either done as if/else or if the compiler chooses to implement switch/case that way) then if value=='a' it finds the right path immediately but later values take more if/else test until it hits the match - so 'h' takes longer than 'a'

Last Edited: Tue. Jul 24, 2018 - 02:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting, and good to know!

 

 

On the subject of switch case, would this work..? :

 

////////////////////////////////////////

switch (value) {

  case value > 3: something; break;

  case value < 4: something; break;

////////////////////////////////////////

 

...can I compare a numerical value to something within the switch case? (e.g. "value > 3")

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Nope, case (in standard C) only allows you to compare with specific values, not ranges. However avr-gcc has an extension (available if you use -std=gnu99) which allows for:

 

switch (value) {
  case 0 ... 3: something; break;
  case 4 ... 255: something; break;
  etc.

(I'm just guessing what the upper limit of the >3 range is here!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

spitta wrote:
Question about writing C code for an arduino atmega328p

 

Note that none of this is specific to Arduino or AVR - this is all standard 'C' (apart from the GCC extension - which is not limited to avr-gcc)

 

Here are some 'C' learning & reference materials: http://blog.antronics.co.uk/2011...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

One other option for the specific case shown in #1 - where there is a simple selection of 1 output value for each input value - is to use a Lookup Table.

 

EDIT

 

Actually, that's not quite the case in #1:

if (value == 'a')
  do something;
if (value == 'b')
  do something;
if (value == 'c')
  do something;
if (value == 'd')
  do something;
if (value == 'e')
  do something;
if (value == 'f')
  do something;
if (value == 'g')
  do something;
if (value == 'h')
  do something;

 

The Lookup Table is most suitable where the actions are not "do something" but "assign a value" - and all to the same variable:

if (value == 'a')
  result = 'Q';
if (value == 'b')
  result = 'W';
if (value == 'c')
  result = 'E';
if (value == 'd')
  result = 'R';
if (value == 'e')
  result = 'T';
if (value == 'f')
  result = 'Y';
if (value == 'g')
  result = 'U';
if (value == 'h')
  result = 'I';

 

Thus

char lookup_table[] =
{
   'Q',
   'W',
   'E',
   'R',
   'T',
   'Y',
   'U',
   'I',
};

result = lookup_table[ value - 'a' ];

You would, of course,  need to ensure that 'value' was  in the valid range before using it to index the array ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Jul 24, 2018 - 02:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
is to use a Lookup Table.
As I say the compiler *may* choose to implement a switch/case this way - but you can't be sure - it's up to it what it thinks is best.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I expanded my post.

 

The lookup table is particularly useful when you just want to get a value - rather than to choose to do something.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Punters do not have enough confidence in modern compilers.

 

GCC does an excellent job.   You should just give it straightforward code and it will generate efficient code.

 

Once you start tying its hands you will suffer.

 

Incidentally,  C compilers selected best code for switch in the 1980s.    And they have improved since then.

 

If you think you can do a better job,  study the generated ASM in a Simulator.   Danish people are very good at this.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Punters do not have enough confidence in modern compilers.

The problem actually seemed like insufficient awareness of the 'C' language?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I occasionally stop by this sub-forum, but usually stay out of the discussions as I am a hacker at best, don't know C, and don't know much about structures and inheritance and this, that, and the other that real programmers know and understand well.

 

That said, it seems to me that one of the key differences between the long series of  If … Then … statements and the series of If … Else If … Else If … Else If … … Else … End If approaches is that the second method automatically incorporates a limit testing on the input variable, (A to H in this case).

 

The Else … section can automatically capture an error when the input is outside of the expected range.

 

Otherwise one might either have a separate valid range test before entering the block, or put a Flag within each If … Then... to indicate that at least one section of the code had successfully been executed.

 

Even though adding an instruction to set a Flag within each If … Then … would take 8 lines of code, (A through H), the execution time is minimal, as it is only actually executed once, for which ever section it actually processed.

Clearing the Flag at the start and testing it at the end would take a couple lines of code.

 

The Else If...  Else...  approach just handles that for you, automatically and seamlessly.

 

As the OP is interested in speed, one might expect the Else If to be a tad bit faster, (unverified, one would have to check the generated code), as a series of If … Then … have to set up the test for each test, while the Else If variant might well keep the comparison variable stored within a register and not have to keep setting it up for each test.

 

My last comment, before crawling back under my rock..., is just a reminder to the OP that it is generally best to get the overall program up and running, and then worry about optimizing bottle-neck sections of code, if needed.

Often times, at the end of the day, it just isn't needed or worth the effort.

Digital Signal Processing and Video GLCD driving are two obvious exceptions where highly optimized routines certainly come into play.

 

JC 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

DocJC wrote:
The Else If...  Else...  approach just handles that for you, automatically and seamlessly.
So does "default:" in switch{}/case

 

Personally I have a feeling that OP simply did not realise his original code could be more efficient with "else if's" and once you head down that road switch{}/case is just more syntactically pleasing for the maintainer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The big difference id that the Else If drop the rest of the IF's when it find a true If.

 

And by the way the  If … Else If … Else If … Else If … … Else … End (and the compare are known at compile time) , the GCC will make a switch case (with break).

 

 Danish people are very good at this.

No I guess I'm the only one :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Go on,  Doc.   I don't know Basic.   But there is bound to be some form of IF, ELSE, ON GOTO, ... and probably even a SWITCH

 

Yes,  most constructs have a default route.    The C switch compares each case: and falls through to the default: block

 

The important lesson is to read the documentation of your chosen Programming Language.    And obey the syntax rules.

 

There is little point in worrying exactly what the Compiler does.   Just that it does what it said on the tin.

I bet that your Basic Compiler does a good job.   But I am not going lose any sleep.   I would just trust it to do its job correctly.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Ah, that'll teach me to stick my nose in where it doesn't belong.

 

I missed the "Default" block at the end, I guess I should have read the code more carefully.

 

And yes, the other nice feature about the Else If construct is the early exit from the long list of If Then's , once one is executed.

 

Basic has the same constructs.

If ... Then ...

 

If ... Then …, Else ...

 

If .. Else If … Else If … Else If …, etc. Else.

 

It also has a "Select Case" statement, similar to the Switch statement discussed above.

 

Except for all of those crazy braces and "double operators" I suspect the two languages are more similar than not.

 

I had to open my compiler's help and look for an On Goto statement.

In Bascom it is called On Value, (On variable Goto/Gosub label1 [, label2...] [, Check]

 

Interestingly, the [, Check] forces a check on the range of the variable and the number of subroutines to either Goto or Gosub, so that the stack isn't corrupted.

That must be a carry over from the earlier days of the compiler, as I can't, at the moment, think of other such cases within the language where the instruction itself has an optional error checking feature.

As the variable is 0 based, and I don't think setting the default base to 1, (Config Base instruction, (useful for arrays, sometimes)), changes that, I suspect that the On Value instruction was the source for many "bugs", and lead at some point to the range checking option.

 

Perhaps others use the instruction a lot, but I suspect it also might be an old instruction just given the Goto option for jumping about the code.

Perhaps the instruction was created when Gotos were still more commonly used.

I don't think I've used a Goto in years, and it seems there are other constructs that are available and easier to debug.

 

Live and learn.

 

I now know a smidgen more about C, and about another Basic instruction I've never used. 

 

Last comment for the OP, again, is that if the frequency of occurrence of the variable, A through H, is not uniformly distributed, then it makes sense to put the variable that occurs most often first in the list, to improve the speed of the program, (the stated goal).  i.e. if "C" occurs 1/2 the time, then make it the first variable tested, don't blindly put the variables in alphabetical order.

 

Somewhat off topic:

 

I am amazed at the number of instructions in Bascom, (and ZBasic).

My last project about filled at 32K chip, and I'll bet I used less than 10% of the available instructions, (or even less!).

While looking for anything with a Goto in it, I spotted LoadWordAdr, which loads the Z register and sets RampZ (if available).

That's another one I've never used, and haven't really got a clue as to when it might be useful.

 

Last comment, speaking of languages...

 

My next door neighbor is also a physician, a cardiologist.

 

The other day he asked me what I know about Phython, as he now wants to learn it.

He hasn't programmed since high school / college on his Atari system.

 

My Uncle, a retired radar engineer, is in his mid-80's and still programs in Fortran.

 

If I ever retire I'm going to be a very busy person, with a long list of projects to do, and a couple of languages to learn!

 

JC

 

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I assume that Bascom and all the other Basics for AVR are compiled languages.

In the 1970s and 1980s home computers like Apple and CBM used interpreted Basic.

 

The horror stories about one-letter variables and slow programs are from those Basic interpreters.

 

I bet that your Bascom can use sensible variable names and run efficient programs.

 

You can construct bad programs in any language if you try hard enough.

 

Straightforward code generally lets a Basic, C, C++, ... compiler do a pretty good job.

Not only does the program work but you can read and understand it too!

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The really important factor, which I do not think was emphasized enough, was that there are major logical difference between

 

if ( value == 'a' ) {
    do something;
}
if ( value == 'b' ) {
    do something;
}
if ( value == 'c' ) {
    do something;
}

and

if ( value == 'a' ) {
    do something;
}
else if ( value == 'b' ) {
    do something;
}
else if ( value == 'c' ) {
    do something;
}

and 

switch (value) {
    case 'a': something; break;
    case 'b': something; break;
    case 'c': something; break;
}

Let me give an example. Why anyone would do this, I don't know, but it does illustrate what happens. Suppose that the first version is implemented as

if ( value == 'a' ) {
    value = 'b';
}
if ( value == 'b' ) {
    value = 'c';
}
if ( value == 'c' ) {
    value = 'd';
}

If you enter with value being 'a', then the first changes value to 'b'. The second test is then evaluated, found to be true, and value is changed to 'c'. Then then third test is evaluated, found to be true, and value is changed to 'd'.

 

But, in the second construction with the else-if tests

 

if ( value == 'a' ) {
    value = 'b';
}
else if ( value == 'b' ) {
    value = 'c';
}
else if ( value == 'c' ) {
    value = 'd';
}

If it enters with value being 'a', then value is changed to 'b' AND THAT IS THE ONLY TEST EVALUATED! At the end of the chain, value = 'b' compared to the first, where value = 'd'.

 

The switch version

 

switch (value) {
    case 'a': value = 'b'; break;
    case 'b': value = 'c'; break;
    case 'c': value = 'd'; break;
}

logically behaves like the if( )- else if() construction and only one test is executed. Here, also, if we enter with value = 'a', the result at the end of the chain is value = 'b'.

 

Thus, you HAVE TO construct the chain of tests to do the testing the way YOU need. 

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think things like single character var names were because all the source had to be kept in RAM and it was a very precious resource so you couldn't have 10 bytes every time a variable with a ten byte name was referenced. (of course a lot of it was tokenised)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There were lots of resulting "features" when you squeeze everything into an interpreter.

 

It was pretty clever that they managed to achieve such a lot with minimal RAM and ROM.   It was enough to impress the home computer enthusiast.

 

Nowadays you use the power of a PC to compile an efficient program that can run on the minimal RAM and ROM.

i.e. you use GB of resources to create a HEX that runs on a 2kB ATtiny25

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
if ( value == 'a' ) {
    value = 'b';
}
else if ( value == 'b' ) {
    value = 'c';
}
else if ( value == 'c' ) {
    value = 'd';
}

Ok the names a bad (it's cut and paste).

 

For those that aren't used to state machines this and example of a typical state machine (ok it should probably also do something ).

 

Question to OP:

 

What is "do something" is it only assigning one variable, more than one (but the same just with different values), does it call a function. 

Without knowing that it's hard to really give a full answer. (a table of function pointers could come into play)

 

And are the values to compare with nicely in row (as you show), or are there big "holes" like compare for '0' 'A' 'N' 'Y' 'q' etc.

 

Different compilers have different ways to decide how to implement a switch (where all case's end with a break).

if many values in a row the some compilers will like to make a table, where others will make a binary search. (I know that for the LCC compiler (the one imagecraft use) you can set how full a row needs to be before it switch over)

If you make a state machine and don't care about the real numbers (you give the states names any way, like LED_ON LED_OFF HIGH_TEMP) you can hint the compiler

by declaring those as enum's. If this are chars coming from a UART then you probably can't do that.     

 

 

 

    

 

 

  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a little advanced, but you could use a table of function pointers.  This is from google result for "C language  table  function pointers"

Take your letter selection and subtract 0x61 to get an (zero-based) index that is based on the (lower-case) alphabetical letter; i.e. 'a'=0, 'b'=1, 'c'=2, etc...

This number is your jump index into a table of function pointers.   When you select "b", execution will jump to the code found at the beginning address of do_something_B.

void (*pf[])(void) = {do_something_A, do_something_B, do_something_C, do_something_D,
do_something_E, do_something_F, do_something_G, do_something_H };

void test(const INT jump_index)
{
    /* Call the function specified by jump_index */
    pf[jump_index]();
}

The above code declares pf[] to be an array of pointers to functions, each of which takes no arguments and returns void. The test() function simply calls the specified function via the array. As it stands, this code is dangerous for the following reasons.

  • pf[] is accessible by anyone
  • In test(), there is no bounds checking, such that an erroneous jump_index would spell disaster

A much better way to code this that avoids these problems is as follows

void test(uint8_t const ump_index)
{
    static void (*pf[])(void) = {fna, fnb, fnc, ..., fnz};

    if (jump_index < sizeof(pf) / sizeof(*pf))
    {
        /* Call the function specified by jump_index */
        pf[jump_index]();
    }
}

The changes are subtle, yet important.

  • By declaring the array static within the function, no one else can access the jump table
  • Forcing jump_index to be an unsigned quantity means that we only need to perform a one sided test for our bounds checking
  • Setting jump_index to the smallest data type possible that will meet the requirements provides a little more protection (most jump tables are smaller than 256 entries)
  • An explicit test is performed prior to making the call, thus ensuring that only valid function calls are made. (For performance critical applications, the if() statement could be replaced by an assert())

This approach to the use of a jump table is just as secure as an explicit switch statement, thus the idea that jump tables are dangerous may be rejected.

 

above is from   https://barrgroup.com/Embedded-S...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 3

In my last project I was checking 512 individual bits in a packet that had no real sequence but similar functions were spread over several bytes.

 

The only thing I could do is to use if statements, I used so many that the compiler run out of ifs and had to go and buy a few boxes from Officeworks.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The original motive for the question was really just to figure out different techniques to perform this same task. I've used many lengthy strings of if-else statements in the past, and was always curious of other ways to do it. In particular, which technique would be "quickest".

 

For example, if I were to be reading sensor data every time an external interrupt occurs, but I don't know how often the interrupt may occur, which is the quickest technique to "do something" with the data? (e.g. store the data, or trigger a particular relay, etc.) --hoping that I finished "doing something" before the next interrupt abruptly occurs.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

spitta wrote:
For example, if I were to be reading sensor data every time an external interrupt occurs, but I don't know how often the interrupt may occur, which is the quickest technique to "do something" with the data? (e.g. store the data, or trigger a particular relay, etc.) --hoping that I finished "doing something" before the next interrupt abruptly occurs.

 

Your AVR is running in the nanosecons/instruction (unless you are running at 1 megahertz or lower).  Unless your Sensor is outputting data at some insane rate, I would think that in your ISR you would simply save the data to a volatile variable/array, then jump back to the main loop to analyse this data and 'so something' before the next ISR hits with great ease..

 

East Coast Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I know that my construction is a bit odd, but I was trying to create something that would end up quite different from what one might expect.The purpose was to show a potential failure mode. 

 

Whether one constructs a chain of if() or a chain of if()... else if () ... else if () depends totally on what the program creator WANTS to happen. the if() chain has the potential of behaving very differently compared to if() ... else if () . The second behaves, logically, like a switch block. However, with the debugger, I see the program going, test by test, through the chain. In a switch block, watching the debugger, it appears to jump directly from the switch statement to the desired case statement. Whether or not one is really faster than the other has to be determined by checking the assembly code that is created by the compiler.

 

And, as others have noted, relative speed may vary according to a number of secondary factors. What may be faster in one case may not be faster in another.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

spitta wrote:
For example, if I were to be reading sensor data every time an external interrupt occurs, but I don't know how often the interrupt may occur, which is the quickest technique to "do something" with the data? (e.g. store the data, or trigger a particular relay, etc.) --hoping that I finished "doing something" before the next interrupt abruptly occurs.
ISR's should be written to be over in a handful of microseconds (esp on mega/tiny where there is no interrupt priority scheme). While an ISR is running it blocks everything else (both main and any other ISR that may want to run). So you shouldn't spend ages in an ISR actually processing received data. Just do the absolute minimum that must occur at the time of the event (which usually means storing the received value somewhere - possibly in a circling buffer). Have lower priority code in the main() loop to then accept and process the arrived data.

 

Only put the entire data processing of the received data in the ISR if something MUST happen immediately (like you have to set an output as a direct result of what just arrived).

 

As for optimisation - don't bother until you need to. Just write clear, concise C and let the compiler handle things - 98% of the time it does a really good job. If you later analyse things and find you have some bottleneck then just concentrate on that one area to see if anything can be done. IF..ELSE IF .. ELSE IF (aka SWITCH / CASE)  is going to be a little more efficient than a cascade of IF .. IF .. IF.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
As for optimisation - don't bother until you need to.

Absolutely!

 

As the well-known saying goes,

Premature optimisation is the root of all evil

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

As the well-known saying goes,

Premature optimisation is the root of all evil

To that I have to add that at bad structure (for the job on hand) from the beginning is even worse.

 

And that is easy for us that have done this for a long time to know what that is, and still often when it's done and everything works, you still have the feeling of, if I have known what I know now I would have done it different.

 

What I try to say is before you start try to get a overview over the job and for a beginner how long time (and resources) does the different parts take. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sparrow2 wrote:
bad structure (for the job on hand) from the beginning is even worse.

Indeed.

 

What Cliff pointed out about ISRs (in #30) is a case in point.

 

It's not something that can just be "bolted-on" as an afterthought.

 

Quote:
before you start try to get a overview over the job and for a beginner how long time (and resources) does the different parts take. 

Good grief - next you'll be saying we should design things before we start coding!!

 

surprise surprise

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Good grief - next you'll be saying we should design things before we start coding!!

 

Heaven forbid...

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

even the cat can help ...
Image result for feline state machine

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Funnily enough, this came up in another thread only the other day:

 

 

Simonetta wrote:

In school I had a plastic template for tracing out the flow chart symbols

 

I wrote:
So did I:

 

ICL was a British computer manufacturer; "CES" was "Computer Education in Schools" - a programme which they sponsored.

Do they not teach the kids this stuff any more ... ?

 

frown

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

It's clear from all the threads we get here that no one "designs" stuff any more. They rush straight to implementation, "designing" stuff as they go along in their C editor - absolutely the worst way to go about software engineering. For me the design process is more important than the implementation (which should be quick and trivial if you got the initial design right). Of course you may well run experiments and prototype certain parts of the design in isolation while initially researching how the overall design will fit together. But that (prototyping) seems to be another skill lost to the internet (we want it "now") generation.

 

In a professional environment we use tools such as IBM's Rational Rhapsody and Rational DOORS to do a lot of the design work months in advance of when any coding actually starts to take place.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is what worries me about all the "teach the kids to code" stuff we hear nowadays.

 

Teaching them to code is not the problem - what we need is to teach them to think, and analyse a problem, and devise a solution strategy.

 

Those skills are clearly the ones which are lacking in "all the threads we get here" - and elsewhere.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kind of back to the thread

I remember that one of the C compilers for the 8051 (I think it was the BSO), (sometimes) implemented a hard to debug but efficient way (switch was on a 8bit var.):

 

It would add a constant so the result would give 0 if there was a match:

if first value to check for was 0x10 it would simply add 0xe0 (that is ok and simple).

if 2. value now was 0x30 it would add 0xf0 (because 0xe0+0x30+0xf0=0x(2)00 )   

etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think schools don't want kids to be getting bored with doing all the paper work in advance and then only spend a very short time doing the fun stuff.

even in my time (90ies) at school we had to create flow charts and state diagrams ( think they were called pds/psd or something like that) were you would see exactly what would be happening with if then else statements and loops.

We were tolled that about 80% of coding was not coding but thinking how the coding should be done so making the charts and diagrams. For the practical assignments we had to also start with the charts, get those approved and only then we were allowed to continue with the actual coding. at least that is how the flow was supposed to be. I do recall a couple of times were no charts were delivered until almost the last hours of practicum and then the next lesson all the code was given without flow approvement. these guys also just started coding and made the charts when they were done as they hated doing that. they always passed by marginal numbers as the code did what it had to do in the end and for the practicums that was enough for them. 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

We back in the day there were two programming jobs: system analyst and programmer. The job of "programmer" was actually fairly low skilled (and low paid) whereas the analysts (who designed what the programmers should implement) were the "clever ones" and paid the big bucks. This madean even clearer distinction between the design and the implementation. Nowadays it seems no one bothers with analysis/design but just stumble through implementation, making it up as they go along. Really quite sad!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Teaching them to code is not the problem - what we need is to teach them to think, and analyse a problem, and devise a solution strategy.

I'm not so certain.  Some of the STEM push is reaction to "we've taught too much thinking and not enough actual DOING."  Bring back shop classes, Home Ec, Coding, and so on.

Enough with all the people who have been "taught to think", but never learned to apply that thinking to the actual real world.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not directly related to this, but have just been watching Inventing the Impossible: The Big Life Fix  (on BBC2) people with interest in invention should see it.

 

It reminded me a bit of medical frontiers on NHK.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
we've taught too much thinking and not enough actual DOING.
I guess Arduino is actually a GoodThing(tm) because it already comes with most of the low level implementation of most of the code needed already "done". So it leaves the designer to simply concentrate on the high level design. So rather curiously it may be creating "the right kind of programmers" ! :-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I taught myself BASIC from the book my grade eight (eighth grade to those of you South of the border, year nine to those of you across the pond) teacher heaved at me.  I was getting into trouble a lot for not paying attention, I guess he figured I was bored and this would keep me out of trouble.  Of course the book had little or nothing on design concepts or methods.

 

With similarly unstructured abandon, I taught myself 6809 assembler.

 

Later in high-school (I think it was grade ten) I took a formal computer science course.  Back then, even at that early level, our teacher drilled into us the principles of formal design.  The first assignments concentrated on flowcharts and pseudo code.  We weren't even allowed into the terminal room (our school shared a VAX 11-750 with three other schools via a 'concentrator' and a leased line) until over a month into the course.

 

I was miserable at first.  "I already know how to program!  Let me at it!"  Thankfully I pushed through that phase.  As a result, many years later, I'm a (possibly slightly) below-average programmer, instead of an abysmally incompetent one.

 

Thank you, Mr. Smith.

 

https://xkcd.com/1691/

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I see that switch statements work much faster than if-else.

Well, no, it doesn't really. It kind of depends how the compiler chooses to implement the swithc() but it'll tend to be a cascading if/else anyway. ch - so 'h' takes longer than 'a'

 

I've rev'enged a lot of code, and switch statements can be very highly optimized by some compilers, including binary decision trees, jump tables, blends of various techniques, etc. Of course, this is partly a factor of the compiler, partly a factor of the problem set, and partly how you construct your switch statements; I've seen ones where I swear the programmer was trying to frustrate any optimization effort.

 

You can also often make your own jump table if your switch statement is dense; the toy example in #1 could be done by making your own jump table as the values are consecutive.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And I will add:

 

And partly the instruction set it's compiled for.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's funny---I will work on a project & someone will give me "the flowchart", with little design thought...then they get antsy when I tell them I'm using a state machine & much of the system "flow"  is determined  at runtime.  "how can you possibly write the program without a detailed flowchart" showing the exact order of every step?"   They also don't know about interrupts & can't comprehend that they don't occur at a certain point in the program (messing up their "flowchart").  They want to design a vending machine as: step 1: light up  insert coin led, step2:read button A, read button B, step3: turn on motor....etc.   It gets funnier when a touchscreen is included...For them an exacting old-school fixed-path flowchart is their comfort zone.

 

 

 

 

When in the dark remember-the future looks brighter than ever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, that might explain why vending machines are often so hard to use; designed by the client! I hate it when the client, instead of telling what it is supposed to do, tells me how to do it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Gotta laugh.

 

I had an old microwave oven, (not a vending machine…), that had a super responsive user interface, (keypad).

One could hit the "Add 30 Seconds" button as rapidly as they wished to do so.

 

Unfortunately, that microwave oven eventually burned out and was replaced.

The replacement is a name-brand consumer electronics microwave oven.

 

And the user interface still bugs me several years later.

 

The Add-30-Seconds button has a built in delay in the interface that means I can't rapidly push it like on the old microwave.

 

In my mind, as I've not dissected the machine, I envisioned the old unit as having an interrupt driven U.I.

Hit the Add 30 Seconds button and the countdown timer is instantly updated.

 

The new UI plods along, slow as can be, eventually reading the keyboard and processing the command.

 

I suspect the old machine wouldn't match the new machine designer's flow chart...

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suspect the old machine wouldn't match the new machine designer's flow chart...

Yeah, I've run into too many people that have a step-by-wait--wait-step mentality.   I nicely tell them their detailed charts are nearly useless (and that's being hugely generous).

"Our flow chart shows you read the + key right after reading the - key, then read the volts key, correct?"  Uh, no...I read any key state & respond to the key currently being pressed.

"Then how do you know what order to read the keys if its not on the flowchart?"

When you see how they flowchart timers & processes that depend upon those, you sort of want to throw yourself through a concrete wall. 

 

========

My washing machine must have a state machine dependent upon the door being locked & some dead-end sequences.....if cycling power & pushing all buttons & cycle options randomly still won't unlock the door, they provide a built-in string you can pull as a backup.

 

I also happened to know of a secret demo mode that sets all the washer's different leds blinking around in some fantastic nonstop pattern...but the only way (as far as I know) to stop it is to unplug the machine.  I set it on one at the store and didn't think much about it...two weeks later this machine that had set there for 2 years was suddenly gone!  I realized they probably couldn't figure out what was "wrong" or how to stop it  & assumed the machine was defective & sold it in the as-is isle at 1/3 price.

 

 

 

 

 

 

 

  

When in the dark remember-the future looks brighter than ever.

Pages