Writing a Library for Arduino but with out delay() in the example please

I found the article at: https://docs.arduino.cc/learn/contributions/arduino-creating-library-guide helpful but feel it would be more helpful if written with out the debilitating delay() function.

Also some examples where the external calling program needs to access internal variables and the library functions need to set global variables or something similar.

The examples might be rewritten so that they interact with an LED and a switch perhaps.

I have written a program making time laps photographs and stepping a stepper motor and I am trying to make libraries out of my code with out using spaghetti.

FYI, I wrote a class in the body of my main .ino program but is was very difficult to move it into a .cpp and . h file and fight variable scope. Although I succeeded it was after so much trial and error I can not claim I understand totally what I did.

My project of which I wrote is here: MerakDubhe/firmware/MerakDubhe_Controller at main · ForrestErickson/MerakDubhe · GitHub

do you have a question or was that just an opinion?

Regarding, "do you have a question or was that just an opinion?"

I was responding in the spirit of the solicitation to do so in the original article,

If you have any problems or suggestions, please post them to the Software Development forum.

Where I am now in my growth as a programmer I feel there needs to be more information helping users create classes. Perhaps it is there but I have not found it yet.

The arduino language is C/C++ and the handling of classes in arduino is no different from the general one for the language. In order to understand the topic, any good textbook can be used.

OK.

Regarding, "The arduino language is C/C++ and the handling of classes in arduino is no different from the general one for the language. In order to understand the topic, any good textbook can be used."

I am struggling to understand this very thing but I believe there are UNIQUE to the Arduino IDE constraints or methodologies to be "overcome" by the new user. These need to be better explained. Or demonstrated with a series of examples of increasing generality.

I didn't notice those...
Why limit yourself to "explanations classes in arduino" when thousands of excellent books about classes in C++ have been written in the world

After pondering our discussion some more I again asked google the following,

The result is I found this explanation with a "hack" that worked in the Arduino IDE to let a Class be declared and defined in a tab if you "overcame" the IDE by moving to a file such as "_main" the setup() and loop().
See: https://www.radishlogic.com/arduino/use-c-class-arduino-ide-without-creating-library/

I conclude that the Arduino IDE is so very close to naturally supporting Classes in Tabs that it is of value to raise the issue.

Perhaps there is some place where I am to make feature requests?

You do not need any "hack" for it

Let us declare class in the main sketch:

class MyClass {
 public:
     int x;
     
     void set_par(int a) {
          x=a;}
          
     int get_par() {
     return x;}
};

MyClass cc;
void setup() {
Serial.begin(9600);
cc.set_par(2);
Serial.print(" Value = ");
Serial.println(cc.get_par());
}

void loop() {}

and see how easy it is to convert it to a separate file
First move the class declaration to the file myclass.h:

class MyClass {
 public:
     int x;
     
     void set_par(int a) {
          x=a;}
          
     int get_par() {
     return x;}
};

and edit the main .ino

#include "myclass.h"
MyClass cc;
void setup() {
Serial.begin(9600);
cc.set_par(2);
Serial.print(" Value = ");
Serial.println(cc.get_par());
}

void loop() {}

After that save the myclass.h to the same dir as your .ino and close and reopen Arduino IDE

the really important thing you really need to know is that the IDE will try to guess which files to include in the compilation / link for you and will also generate forward declaration for functions in the .ino files.

but for classes declaration just go with C++ (a .h and a matching .cpp file or a .hpp file)

Hello b707,

Thanks for illustrating the development methodology. It is something like I attempted.

I would summarize it as:
Develop in the main tab ABOVE the setup() and loop() and then move.

I think it is proper that a fuller example would include putting all Class code in a .cpp file.

It is when I did that that move to .h and .cpp I began to fight variable scope with out a clear vision for the end goal.
My class was manipulating some global (which represented hardware states for example) and responding to some user input through globals and when I moved it to a .cpp file much was broken. IIRC I wrote some functions to set member variables to fix some or most of the problems but near the end I was fatigued that I literally was working trial and error clearing error messages with out understanding the big picture.

So I read read the instructions for making the Library for Arduino to which I linked helped me a lot but was not general enough. Thus my request.

Could my request be reworded better?

this is your big mistake
One of the basic paradigm of the Object Oriented programming is that the class should not use any external data directly (for example as global variables), the one correct way doing it - to use dedicated class methods for input and output data - i.e. "getters" and "setters"
And again, this is nothing Arduino specific - it's all explained in any Object Oriented Programming textbook. I do not consider it correct to state these principles in arduino examples - this material is too extensive and can hardly be presented in a short form. Writing libraries is already beyond the needs of ordinary users, and those who want to go further need to dig into the study of C ++

There is one thing to be aware of. You should should not access hardware in a constructor; so e.g. pinMode should not be used. Reason is that the hardware is not be initialised yet. You will find that classes that access hardware always have a begin (or similar) method.

1000 Thanks for the tip.

I will have to reexamine what I have written for compliance.

Here from my .h file is what I believe constitutes the constructor and it does not access the hardware.
If it needs some stones thrown at it please let'm fly.

/*
  cameracontrol.h - Library for controling a camera focus and shutter using an open drain on Aruino.
  Created by Forrest Lee Erickson
  Date: 20220702
  Released into the public domain.
*/

// keep from including twice
#ifndef cameracontrol_h
#define cameracontrol_h

#include "Arduino.h"

class WiredCamera {

  public:
      /*  Wiring from Railduino
        D6~              /Focus    ?ring?
        D7               /Shutter  ?tip?
    */
    //    const  int EXPOSURE_TIME = 30000;  // 30 seconds for time laps
    const  int EXPOSURE_TIME = 1000;  // 1 second for development.
    const  int nFOCUS = 6;  // Pin assignment. Make low to trigger auto focus.
    const  int nSHUTTER = 7;  // Pin assignment. Make low to trigger open shutter.
    const  int  FOCUS_DELAY = 1000;  //mSec delay from focus to shutter release.
    //long OffTime;    // milliseconds of off-time
    const long PHOTO2SD = 3000;    // milliseconds of time to load photo into SD card


    //Set up the pins for this instance.
    WiredCamera(int focus_Pin, int shutter_Pin);

    void printCameraPins();
    void setupCameraWiredInterface();
    void setAutoFocus();
    void focusAndPhoto();
    void makePhoto();
    bool updateTimeLaps();
    void setExposureTimeSeconds(int seconds);
    void printExposureTime();
    void setLastExposure(bool isLastExposure);

  private:
//    int _focusPin = focus_Pin;
//    int _shutterPin = shutter_Pin;
    int _focusPin = nFOCUS;
    int _shutterPin = nSHUTTER;
    int _focusDelay = FOCUS_DELAY;
    int _exposureTime = EXPOSURE_TIME;
    unsigned long _previousMillis = 0;    // will store last time LED was
    bool _isShutterOpen = false;
    bool _isLastExposure = false; //Lets start able to make expsoures.

}; //end of class decleration



#endif

This is the prototype of the constructor. You have a .cpp file as well (I guess) that has the implementation and that is where you should not access the hardware.

//Here is the .cpp

/*Wired Camera Control for Focus and Shutter
   By Forrest Lee Erickson
   Date: 20220701
   License: Released into the public domain, dedicated to the public domain
   Warrentee: This code is designed to kill you and render the earth uninhabitable but is not guarenteed to do so.

   Developed for Canon T3 camera and tested with the same.  See my Railduino project too.
*/

#include "Arduino.h"
#include "cameracontrol.h"

/*Wired Camera Control for Focus and Shutter
   By Forrest Lee Erickson
   Date: 20220701
   License: Released into the public domain, dedicated to the public domain
   Warrentee: This code is designed to kill you and render the earth uninhabitable but is not guarenteed to do so.

   Developed for Canon T3 camera and tested with the same.  See my Railduino project too.
*/


//Set up the pins for this instance.
WiredCamera::WiredCamera(int focus_Pin, int shutter_Pin) {
  _focusPin = focus_Pin;
  _shutterPin = shutter_Pin;
}//end WiredCamera

void WiredCamera::printCameraPins() {
  Serial.print("Focus pin: ");
  Serial.println(_focusPin);
  Serial.print("Shutter pin: ");
  Serial.println(_shutterPin);
}//end printCameraPins

/*
   Focus and Shutter pins are high impedance at power up. Set for input just to make sure.
   Write the ditital output as LOW, but since input the camera is not changed.
   To activate foucus or shurter release write pinMode from input to output and then back to input.
*/
void WiredCamera::setupCameraWiredInterface() {
  pinMode(_focusPin, INPUT);  //Set as input for high impedance.
  pinMode(_shutterPin, INPUT); // Set as input for high impedance.
  digitalWrite(_focusPin, LOW);  // Set for pin low to sink current when low impedance.
  digitalWrite(_shutterPin, LOW);
  //delay(50);
}//end setupCameraWiredInterface

void WiredCamera::setExposureTimeSeconds(int seconds) {
  _exposureTime = 1000 * seconds; //milliseconds for expsoure time.
  Serial.print("ExposureTime:  ");
  Serial.println(_exposureTime/1000);
}//end setExposureTimeSeconds

void WiredCamera::printExposureTime() {
//  _exposureTime = 1000 * seconds; //milliseconds for expsoure time.
  Serial.print("ExposureTime:  ");
  Serial.println(_exposureTime/1000);
}//end setExposureTimeSeconds

void WiredCamera::setAutoFocus() {
  // Trigger auto focus before photo
  pinMode(_focusPin, OUTPUT);  // Make low impedance
  Serial.print("Focusing! ");
  delay(_focusDelay);
  pinMode(_focusPin, INPUT);    //Make high impedance.
  Serial.println("Focus set");
}//end setAutoFocus()

void WiredCamera::focusAndPhoto() {
  // Trigger auto focus before photo
  pinMode(_focusPin, OUTPUT);  // Make low impedance
  Serial.print("Focusing! ");
  delay(_focusDelay);
  pinMode(_focusPin, INPUT);    //Make high impedance.
  Serial.println("Focus set");

  //Shutter release
  pinMode(_shutterPin, OUTPUT);  // Make low impedance
  Serial.print("Shutter release ");
  //delay(_focusDelay);
  delay(1);
  pinMode(_shutterPin, INPUT);    //Make high impedance.
}//end focusAndPhoto()

void WiredCamera::makePhoto() {
  //Shutter release
  pinMode(_shutterPin, OUTPUT);  // Make low impedance
  Serial.println("Shutter release ");
  //delay(_focusDelay);
  delay(500);
  pinMode(_shutterPin, INPUT);    //Make high impedance.
}//end makePhoto()

void WiredCamera::setLastExposure(bool isLastExposure) {
  // Make local variable
  _isLastExposure = isLastExposure;
}//end setLastExposure()

//Make photo of time _exposureTime. Updates _isShutterOpen returns isTimeLaps
//Need to have this setup ready to go when isTimeLaps becomes true.
bool WiredCamera::updateTimeLaps() {
  unsigned long currentMillis = millis();
    if ((currentMillis - _previousMillis >= PHOTO2SD) && !_isShutterOpen) {//Card written so make photo.
      pinMode(_shutterPin, OUTPUT);  // Make low impedance
      Serial.println("Shutter open ");
      _previousMillis = _previousMillis + PHOTO2SD;  // Update the time
      _isShutterOpen = true;
      return(true); //Shutter not open so we are writing to card.
    }//end time has elapsed
    else if ((currentMillis - _previousMillis >= _exposureTime) && _isShutterOpen) {
      pinMode(_shutterPin, INPUT);    //Make high impedance to close.
      Serial.println("Shutter closed ");
      _previousMillis = _previousMillis + _exposureTime;  // Update the time
      _isShutterOpen = false;
      if (_isLastExposure) {
        _isLastExposure = false;
        return(false);//Return is time laps
      }else {
        return(true); //Not yet at last exposure
      }//end else if >exposure time and shutter open      
  }//end isTimeLaps
}//end updateTimeLaps

// };//end WiredCamera class

Your constructor does not access the hardware

And later you have the below that accesses the hardware

So your class is OK from that perspective.

1000 Thanks for your helpful suggestions and review.