is there a place with a collection of "functionality" examples?

Hi everybody,

is there a place somewhere on Arduino.cc with functionality-examples?

Of course there is the reference that explains the syntax how to use single functions and words of the programming-language.

For beginner it would be very useful if there would be a collection of what I call "functionalities"

I was inspired to this question an example-code posted by horace for a certain "functionality" that I want to use right here to explain what I mean. It is an example about non-blocking timing for "switching off" something after a certain amount of time. First as a very concrete examples using IO-pins then in a more generalised way to make newbees see how they can adapt this functionality to their own needs.

Switch on something depending on a condition becoming true.
If condition changes back to state unset keep switch ON for a certain amount of time then switch OFF

this example uses an IO-input named "SWITCH" to switch on and delayed switching off an IO-pin named "FAN"

loop() {
   static unsigned long MillisSnapShot = 0;
   const unsigned long WaitingTime     = 5000;

   if(digitalRead(SWITCH))           // switch pressed ?
   {               
     MillisSnapShot = millis();      // start timing
     digitalWrite(FAN, HIGH);        // fan ON
   }

   else if((millis() - MillisSnapShot) > WaitingTime) // delay elapsed?
   {  
     digitalWrite(FAN, LOW);         // fan OFF
   }

   // do other things at high speed in "parallel" to the timing

} // end of loop()

written as code-template in a more general way where variable "flag" can be any kind of boolean expression.
As soon as the boolean expression becomes true the action "switch ON" will be executed

As a sideeffect if the boolean expression stays true for some time the timer-variable MillisSnapShot gets updated all the time
which has the effect that switching off will always happen only after boolean-expression becomes false
AND the additional waiting-time os over

example with numbers:

WaitingTime 20 seconds
10:00:00 boolean expression becomes true => switch ON
10:00:01 boolean expression becomes false => WatingTime starts
10:00:21 switching off

WaitingTime 20 seconds
10:00:00 boolean expression becomes true => switch ON
10:00:01 boolean expression still true
10:00:02 boolean expression still true
10:37:40 boolean expression still true
......
11:45:05 boolean expression becomes false => WatingTime starts
11:45:25 switching off

examples for boolean expressions that replace the variable "flag"
( digitalRead(MyIO_Pin == HIGH) )
( digitalRead(MyIO_Pin == LOW) )

( AnalogRead(MyIO_Pin > 100) )
( AnalogRead(MyIO_Pin < 200) )

( MyBooleanVariabe == true)
( MyBooleanVariabe == false)

loop() {

   static unsigned long MillisSnapShot = 0;
   const unsigned long WaitingTime = 5000;

   if(flag) 
   {               
      MillisSnapShot = millis();        // start timing
      // switch "ON"
   }

   else if((millis() - MillisSnapShot) > WaitingTime)  // delay elapsed?
   {
      // switch "OFF"
   }

   // do other things = execute code at high speed in "parallel" to the timing

}  // end of loop()

So my question is:
is there a place where such code-snippets are collected so newbees can look-up these code-snippets for questions like How do I ......

best regards Stefan

an alternative could be to use a state machine to switch between the fan sates, e.g. on, off, delay, e.g.

// switch on fan when switch pressed - when switch release maintain fan for 5 seconds

#define SWITCH 10
#define FAN 5
#define WaitingTime 5000UL

enum FanStates {FAN_OFF, FAN_ON, FAN_DELAY};

void setup() {
  // declare the pins as outputs
    pinMode(FAN, OUTPUT); // Line to FAN Delay Control
  // declare the pins as inputs
    pinMode(SWITCH, INPUT);  // PTT line on Transmitter
}

void loop() {
   static unsigned long int delayTime;
   static int fanstate=FAN_OFF;   // inital fan state
   switch(fanstate) {
     case FAN_OFF: if(digitalRead(SWITCH)){   // switch pressed ?
                      fanstate=FAN_ON;
                      digitalWrite(FAN, HIGH);
                      }
                    break;
     case FAN_ON: if(!digitalRead(SWITCH)) {  // switch released ?
                      fanstate=FAN_DELAY;
                      delayTime=millis();
                      }
                    break;
     case FAN_DELAY: if((millis()-delayTime) > WaitingTime) {  // delay elapsed?
                      fanstate=FAN_OFF;
                      digitalWrite(FAN, LOW);
                      }
                    break;
   }
}

Hello Stefan,

++Karma; // For thinking about ways to help new folk learn.

I don't think what you suggest exists as such. When I came here I quickly realised there was no help for anyone using Nextion displays and as I have used Nextion displays successfully I wrote the Nextion tutorial at the top of the displays' section. This took me some amount of time and I had help and feedback from the people noted at the end. It is not a trivial task to write a decent tutorial, and even with the best will in the world what seems to be a well written tutorial to one person will be difficult to understand and confusing to another.

What I suggest is that you check all the tutorials on the Arduino web site, both the ones at the top of each forum section and the 'official' ones under Documentation, and if you see an obvious gap then write a tutorial to fill the gap. You will need feedback, which I am happy to offer if you are serious, and you will need the support of a mod to get it locked to the top of the appropriate section. In my experience the mods are willing to help provided the tutorial is well written and fills a clear gap in what is already on offer here. You probably ought to solicit at least one other person besides me to provide feedback so you get different opinions. Be prepared to do substantial re-writing based on the feedback you get.

Post as requested. Cleaned up and functional but not finalized.

// Runs on an UNO

// A basic timer that runs when enable is true, else is reset.
// timer1TimedOut true only when timer1AccValue >= timer1Preset, false otherwise.
// When the timer times out a counter is incremented.
// When the counter reaches its preset a boolean is toggled and the
// counter is reset to zero.
// The toggled boolean controls a state machine-driven blink sequence.
// An LED blinks when the toggle is true and is extinguished when the toggle is false.
// These actions are displayed on the serial monitor.

// Demonstrates:
// millis() timer operation + debouncing
// sensing/indicating timer completion
// doing more than one thing at a time
// state change detection
// boolean value toggling
// calling functions with and without passing parameters
// using a switch/case state machine to blink an LED

//#include <ArduinoShrink.h>

uint32_t timer1AccValue;
uint32_t timer1Preset = 1500; // 1.5 seconds
uint32_t previousMillis;
uint32_t currentMillis;

const byte enablePin = A3; // A0-A5 can be used as digital inputs
const byte blinkLED = A0; // and digital outputs.
const int counter1Preset = 3;
int counter1AccValue;
bool timer1TimedOut, timer1TimedOutPreviousState;
bool toggleBool = true;

// blinker function state variables
enum : byte {initialize, blinkerOnCycle, blinkerOffCycle, blinkerOnTtransition, blinkerOffTransition};
byte blinkState;

unsigned long blinkTimer;
unsigned long timerPreset = 750;

// For symmetrical on/off times just use the same time value for both states.
unsigned long blinkerOnTime = 100;
unsigned long blinkerOffTime = 1500;

void setup() {
  Serial.begin(115200);
  pinMode(enablePin, INPUT_PULLUP); // INPUT_PULLUP avoids the need for a discrete resistor.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(blinkLED, OUTPUT); // Common anode connection
  Serial.print("\n\nTimer  Timer  Counter Toggle\n");
  Serial.println(" Acc   Done    Acc     Bit");
  displayFunction(timer1AccValue, timer1TimedOut, counter1AccValue, toggleBool);
  blinkState = initialize;
  delay(3000); // Pause for user to see column headings
}

void loop() {
  currentMillis = millis(); // Take a snapshot of millis() to use for processing.
  if (digitalRead(enablePin) == LOW) { // If input is grounded, enable timer to run.
    timer1AccValue = timer1AccValue + currentMillis - previousMillis;
  }
  else {  // If timer not enabled it is reset
    timer1AccValue = 0;
    timer1TimedOut = false;
  }
  
  // Signal the timer's completion status
  if (timer1AccValue >= timer1Preset) { // If time elapsed, limit timer1AccValue and set timer1TimedOut
    timer1AccValue = timer1Preset;
    timer1TimedOut = true;
  }
  previousMillis = currentMillis; // Update previousMillis.

  digitalWrite(LED_BUILTIN, timer1TimedOut);  // The onboard LED indicates timer status

  // Increment the counter just once for each false-to-true transition of timer1TimedOut.
  // If timer1TimedOut were used unconditioned the counter would increment continually
  // whenever timer1TimedOut is true.

  if ((timer1TimedOut == true) and (timer1TimedOutPreviousState == false)) {
    counter1AccValue++;
  }
  // This is what creates the 'one-shot' behavior
  timer1TimedOutPreviousState = timer1TimedOut; // Remember timer1TimedOut's previous state for next pass

  // When the counter reaches preset toggle a boolean and reset the counter.

  if (counter1AccValue == counter1Preset) {
    toggleBool = !toggleBool; // toggleBool is loaded with the complement of itself.
    counter1AccValue = 0;
  }

  blinkerFunction();
  displayFunction(timer1AccValue, timer1TimedOut, counter1AccValue, toggleBool);
} // end of loop

//--------------------------------------------

void displayFunction(uint32_t timer1, bool timedOut, int counter, bool toggle) {

  // Display runtime values passed from caller
  Serial.print(timer1);
  Serial.print("\t");
  Serial.print(timedOut);
  Serial.print("\t");
  Serial.print(counter);
  Serial.print("\t");
  Serial.println(toggle);
}

void blinkerFunction() {

  // The state machine is enabled/disabled by global variable toggleBool.

  if (!toggleBool) { // blink
    switch (blinkState)
    {
      case initialize:
        blinkState = blinkerOnTtransition; // Set the next state value
      // Fallthrough is deliberate

      case blinkerOnTtransition:
       // This way doesn't constantly hit the Serial print digital write statements
        Serial.println("on cycle");
        digitalWrite(blinkLED, LOW);
        blinkTimer = millis(); // Reset the timer
        blinkState = blinkerOnCycle; // Set the next state value
      // Fallthrough is deliberate

      case blinkerOnCycle:
        if (millis() - blinkTimer < blinkerOnTime) { // Which it will be for awhile since the
          //                                            previous state set timer = millis()
          break;
        }

        blinkState = blinkerOffTransition; // Set the next state value
      // Fallthrough is deliberate

      case blinkerOffTransition:
        Serial.println("off cycle");
        digitalWrite(blinkLED, HIGH);
        blinkTimer = millis(); // Reset the timer
        blinkState = blinkerOffCycle; // Set the next state value
      // Fallthrough is deliberate

      case blinkerOffCycle:
        if (millis() - blinkTimer < blinkerOffTime) {
          break;
        }
        blinkState = blinkerOnTtransition; // Set the next state value
        break;

      default:
        blinkState = initialize; // If invalid state occurs, start at the beginning
        break;
    }
  }
  else {
    digitalWrite(blinkLED, HIGH);
    Serial.print("blinker off  ");
  }
}

I think what you call "functionalities" might be called, "design patterns" in some places. So, "templates for how to accomplish certain things". The examples sort of try to fill that function, but they often don't drill very deep. For example, people are sometimes sent to look at "Blink without Delay" to learn how to make non-blocking code. But it is such a simple demonstration (it only does the same thing each iteration), that it's not immediately obvious how it could be extended - for example, to asymetrically blink, or to synchronously blink multiple LEDs and so on.

With state machines, you really need some design patterns because it is a layer on top of the sequential logic of the programming language itself. If you're smart and work at it, you can create your own (and maybe not even realize it, just think you're pretty clever and just created some obvious higher level techniques to get something done). Really, it places a huge burden on the beginner. So some help with that would be great. Think of how many times people just need a simple timer and can't manage it.

For beginners, they need to be whittled down to the absolute simplest case, while the code posted above is excellent, it is daunting if you don't already know a lot of stuff.

I dislike "code-snippets".
Beginners need working codes.

you wouldn't need an extra explanation "this example uses an IO-input named "SWITCH" to switch on and delayed switching off an IO-pin named "FAN" - if you had just written the const definition and and the two lines in setup.

Beginners often have the problem to not know what to search for, therefore I assume they will not look into a collection of patterns neither.

regarding the code snippet:

be consistent within your example, e.g.

WaitingTime
vs
FAN
vs
flag

Arduino uses camel case for variables, starting with lower letter in their examples.

Yes, after posting that, I thought, "hey maybe we just need more complete examples". But they need to be bite sized examples. That can be a problem when the reality is, it is complicated. For that reason, they need to be pared down to the bare minimum that clearly demonstrates that one thing. One sneaky way of doing that, is nicely encapsulated functions.

aarg:
Yes, after posting that, I thought, "hey maybe we just need more complete examples". But they need to be bite sized examples. That can be a problem when the reality is, it is complicated. For that reason, they need to be pared down to the bare minimum that clearly demonstrates that one thing. One sneaky way of doing that, is nicely encapsulated functions.

HI aarg,
this is very good feedback. I agree: working code containing everything to compile will be much better.
About nicely encapsulated functions I'm unsure. It delivers the functionality but it enables to not learn how it works inside.
A really interested user will look inside and analyse the functions's code to understand it. The users that don't want to will jump over it trying to get finished faster (And will slow down the finishing of their project caused by staying on a lower knowledge-level). But I'm unsire maybe I just have to start with an example doing it both ways and then look at it again.
Maybe it is just one point of view: Nobody ever questions to dig in that deep to analyse the underlying code of commands like "digitalWrite()" etc. And indeed it is not nescessary.
@aarg: could you explain in more details what you mean with "nicely encapsulated"?
best regards Stefan

There are lots of examples included with the Arduino IDE.

I'm not at all convinced that more examples would add value. They are only useful for someone who is expert enough to figure out what the code in the example actually does.

I reckon what will be useful for newbies is a short Tutorial that identifies the problem that needs to be solved and then explains and illustrates how to solve the problem.

Unfortunately the great enthusiasm of the Open Source community for sharing code is rarely matched by an enthusiasm to write tutorials that explain all the details about how the code should be used and what its limitations are. Ideally the documentation (or essay) should be written first and then code should be created to match it. That way the code can be focused on the problem that the text identified.

...R

StefanL38:
About nicely encapsulated functions I'm unsure. It delivers the functionality but it enables to not learn how it works inside.

I disagree, look at my Nextion tutorial. The code is in functions, with one function for each task. The tutorial contains working examples but in order to use the tutorial for your own project you have to understand how it works then modify for your own project. You cannot take my code and paste it unmodified into your project. My tutorial teaches a way of interfacing to a Nextion, but to use it you have to understand how it works. I think your concern applies to classes with nicely encapsulated code blocks that you don't have to understand to use. I did not write my Nextion code like that and I suggest you don't write a tutorial like that. Write functions that illustrate how to achieve something but do not provide a cut and paste solution for someone who cannot be bothered to learn. Keep in mind that your aim is to teach how do do something, not provide complete, polished ready to use code.

A really interested user will look inside and analyse the functions' code to understand it. The users that don't want to will jump over it trying to get finished faster (And will slow down the finishing of their project caused by staying on a lower knowledge-level).

Don't worry about that, you cannot make someone more interested than they are, that's up to them, not you. They will learn what they need to learn to get done what they want to do. I would think that after 800+ posts you will have noticed that questions on here range from 'just give me code' to 'I really want to learn this stuff but I'm stuck'. I suggest you focus your efforts on the second group and don't bother yourself too much with the first.

Robin2:
Unfortunately the great enthusiasm of the Open Source community for sharing code is rarely matched by an enthusiasm to write tutorials that explain all the details about how the code should be used and what its limitations are.
...R

Robin is spot on with that. My 2 tutorials on here took quite a long time to write, the Nextion one obviously so because of how much of it there is, the common ground one also took months, not because of the amount of content (there isn't much) but because it took me ages to work out what I needed to say and, just as importantly, what I needed to exclude in order to convey one simple, clear message.

StefanL38:
A really interested user will look inside and analyse the functions's code to understand it.

I missed this earlier.

A beginner won't be able to do that, and won't even think of doing it, no matter how interested they are. Jeez they won't even read the stickys that have been created to help them.

And examining code is a very poor substitute for proper documentation - even if the target market is experienced programmers.

...R

StefanL38:
@aarg: could you explain in more details what you mean with "nicely encapsulated"?

I'm suggesting using functions as examples, so the code is visible. Yes, that term wasn't the clearest... what I mean, is that all the declarations are internal (so using 'static' keyword etc.), so that there can't be any guesswork about the things that the function references, or its context. In other words, to eliminate any dependence on some unknown external code. Except, for an example call of the function. I thought that in some cases it might be more succinct than an entire compilable sketch.

In the context of a tutorial, they can't be very useful unless they are utilized in a working sketch, because a tutorial should have a component of demonstration - e.g. an example of input and output is shown. You can't do that with a bare function.

Something about tutorials - it's the quality that is important not the quantity. As proof I cite the legions of presumptuous attempts on other online platforms that frequently propel people here to fill in the huge gaps in explanation or repair the faulty code and amateurish electronics that is offered there.

@Robin2 says,

I'm not at all convinced that more examples would add value. They are only useful for someone who is expert enough to figure out what the code in the example actually does.

The lack of accompanying tutorial in some cases, that was mentioned, contributes to this. But I suggest that there are ways in which many of them could be improved, with more careful construction and internal documentation, to make them more useful in understanding.

Oh, and... yes it is important to define your target audience. There are many levels on which they can work - I've seen tutorials for EE's as well as beginners and hobbyists.

Sometimes there is a general topic that needs a lot of examples to cover. That can be troublesome. For example, cooperative multitasking. That would ideally involve multiple modules on state machines, timing, etc.

Quote from: StefanL38 on Today at 07:11 am

A really interested user will look inside and analyse the functions's code to understand it.

I missed this earlier.

A beginner won't be able to do that, and won't even think of doing it, no matter how interested they are. Jeez they won't even read the stickys that have been created to help them.

*best regards Stefan *

StefanL38:
is there a place somewhere on Arduino.cc with functionality-examples?

So, is reply #3 what you envisioned?

Hi dougp,

it took me some time to remember that you asked about post #3.

Yes this is kind of what I have in mind. Reading your example-code pointed me to an important thing:

I'm a somehow advanced programmer but far away from beeing a real professional.
After looking through your code-example I guess I have an overview which part does what. But I did not analyse all parts.
And i did not understand the logic in all details. Therefore I need more time than reading it once withing 2 to 3 minutes.

If it should be understandable for newbees I guess a shorter code will be easier to understand.
So right now I'm thinking about writing "standard-functions" like separate ON/OFF-Time-Timer, single-shot timer etc.
all the nescessary details will be inside the functions and in the mainloop is just

void loop()
  OnOFFTiming(OnTimePeriod, OffTimePeriod)

etc.
I haven't come to a descision yet if this is the best way

best regards Stefan

StefanL38:
If it should be understandable for newbees I guess a shorter code will be easier to understand.

If your target market is newbies then an explanatory essay is more important than code IMHO. For example, write an essay that presents the information in the comments in Reply #3 and then use pieces of code to illustrate the essay - plus the complete program at the end. And, yes, that takes a lot more time and effort than writing code and adding some comments to it.

On it’s own a comment such as “// This is what creates the ‘one-shot’ behavior” is not going to be meaningful for a newbie. I suspect it will raise more questions than it answers.

…R

Robin2:
If your target market is newbies then an explanatory essay is more important than code IMHO. For example, write an essay that presents the information in the comments in Reply #3 and then use pieces of code to illustrate the essay - plus the complete program at the end. And, yes, that takes a lot more time and effort than writing code and adding some comments to it.

On it's own a comment such as "// This is what creates the 'one-shot' behavior" is not going to be meaningful for a newbie. I suspect it will raise more questions than it answers.
...R

In the reference the basic commands of c++ are explained. This explanation goes not that deep to explain all the underlying details of what the compiler does to realise to make it work.
I don't know these details just a raw estimation from knowing the internals of the famous 6502-based C64-home computer
for example pinMode(pin,mode) will have underlying commands liek
load value from port-direction-register do a bitwise or with value given in parameter pin etc.
The reference does not explain these details. It is not nescessary. So I'm thinking about something similar on the level of functionalities like timers.
providing functions with a certain functionality like "oneshot timer" and a democode that shows how to use this function.
The explanation how its coded inside the function will only be epxlained by some short comments to give a glimpse for the very interested user.
Of course taking much time to learn intensively is - in most cases - the better choice. Though my approach is to give support to the users that don't want to take so much time to study all the basics until their knowledge is so big that they are able to code these functionlities on their own from scratch.

It is the same principle like using libraries. If you use a liquid-chrystal-lib you don't learn all the underlying commands what has to be done in detail to set the cursor into second row, fifth columm
(initialise command mode, send command "set cursor", send raw-number, send columm-number, exit command mode etc.)

You just use "lcd.setCursor(1,5) . It is not nescassary to look inside the library

best regards Stefan

StefanL38:
In the reference the basic commands of c++ are explained.

We seem to be operating on different wavelengths. What I was trying to say in Reply #15 seems to be entirely unrelated to what you have said in Reply #16.

Let’s just agree to be different.

…R

Robin2:
On it's own a comment such as "// This is what creates the 'one-shot' behavior" is not going to be meaningful for a newbie. I suspect it will raise more questions than it answers.

Fair enough. Any comment on the overall concept?

dougp:
Fair enough. Any comment on the overall concept?

No more than what I have said in Reply #15

This may be a matter of style and preference.

...R