Code snippets, anyone?

Some years ago after watching one of Sam’s youtube videos I responded to his call for anyone to maybe have a look at the code he wrote for the Tuner he was working on (which later became an integral part of his VCO). I had a look at the code and after tidying it up a bit and sending it to him he invited me to join this forum.

Following that I built my own version of the tuner in eurorack format and have used it ever since. In the past few years I’ve seen that although this forum is mostly about analog electronics more complex modules tend to be controlled by some processor like an arduino, pi pico or a BluePill. However, there is not much talk about the software that drives these modules other than that people often add a link to their github and that leaves it up to the person interested to find out how that software works. Especially for new comers to software that is often way too complicated.

Currently I’m working on a module that reads inputs from potentiometers, faders, buttons etc. and while I was designing a class for a potentiometer I thought, I need one that is a simple pot, I need one that has a zero middle position (turn left from there you get a negative and right from there you get a positive value) and I need a pot that is quantized, so it return 5 values, and I need one that does the same but has a center value of zero.

I managed to get things working and then thought, wouldn’t other people be interested in these small bits of code (they are too small be be called a library I think) which they could use as building blocks for their own projects?

So I was wondering whether anyone would be interested in a ‘code snippets thread’. I imagine this can be used to show small bits of code. The code should be formatted (standard indentation is enough) so that the code is easy to read, and include a description and a simple test program which demonstrates its use.

8 Likes

This is a fabulous idea. Sam has often mentioned the notes and volts midi code, would links to good examples be ok?

Links would be ok I guess if they lead to an article that describes the code snippet and explains it in detail. Otherwise links would maybe quickly tend to be ‘see my github’, which does not explain anything much.

1 Like

+1 from me. Would this mean that there will be a thread where people post a bit of code alongside an explanation?

That is what I meant to propose.

2 Likes

I definitely agree with this idea - there is a lot of code out there, but often it is “well, this seems to get the job done” code rather than “this is how it works” code. That is one reason I started to pull out specific blog posts of my own onto a “techniques” page, but I’ll be the first to admit it is a little chaotic!

So, yes, I think this is a great idea, and I’d like to put up my techniques page as a starting point until something more useful gets posted :slight_smile:

See: Techniques – Simple DIY Electronic Music Projects

Basically, I’m always happy to talk through anything I’ve posted if anyone spots anything of interest.

Kevin

2 Likes

I love this idea! I’m familiar with some languages, and still getting used to C and others used in microcontrollers, so it’s tricky figuring out how much to “trust” a given source. This seems like it would serve as an excellent resource!

1 Like

As in a verified code thread? Like our stripboard one?

Yep, with added test program or demo/example program as a reference.
Obviously an example may not run on just any microcontroller, but it should run without a problem on the one it was written for. I will try to upload an example of what I image a snippet could look like on this thread soon.

1 Like

Introduction

This code snippet contains some C/C++ code and a C++ class that can be used to read a value from a potentiometer. Furthermore it shows some examples on how to use the code.

Potentiometer code snippet(s)

I will start approaching this code snippet from the view of the user who wants to apply it in his main loop. I’m assuming an arduino nano setup and will write everything following the standard setup(){ ... } and loop() { ... } framework.

Furthermore I’m assuming we use the arduino IDE.
Let’s start with a simple version of the code.


// example program 1

// Include libprintf which makes printing to the serial port SOOOO much easier.

#include <LibPrintf.h>

// Include the potentiometer class
#include "Potentiometer.hpp"

// Here are some constants and global variables (beware of the latter!).
#define ANA_IN_PIN A0
#define SERIAL_SPEED 312500

Potentiometer pot;

void setup() {
 Serial.begin(SERIAL_SPEED);
 // We instantiate the potentiometer and link it to an analog input.
 pot = Potentiometer(ANA_IN_PIN);
}

void loop() {

	pot.tick();

	if (pot.hasChanged()) {
		printf("current value: %d\n", pot.getValue());
	}
}

What does this all mean?
We start the serial port and give it a certain baud rate. You will need to set the output monitor window of the arduino IDE to the same speed.

The pot must be accessible in the setup() and in the loop() subroutine, therefore it must be defined outside of them: ‘Potentiometer pot;’. But before we do we include the file Potentiometer.hpp because that contains the pot’s class definition.

In the setup(){} we instantiate the pot and link it to the analog input pin.
In the main program we can now read the pot’s value, but in order to do so we use a ‘tick’ function. This function should be called as often as makes sense. The pot is not likely to change its value more than a few times a second. I’ll get back to this later. Note, I have found that several libraries that deal with input devices use a tick() or similar function. They inspired me to use one in this code.

If the pot has changed, we want to know its value and in this case print the new value.
The loop() will then restart, tick the pot and print something if it has changed. If the pot has remained the same, nothing will be printed.

I’ve not measured this but depending on the speed of the arduino you are using, the loop will cylce tens of thousands of times per second. If you do not like the idea that the pot is read that often, you could use a delay between successive ticks. There are at least 2 methods of implementing a delay.

Method one: use delay(number_of_milliseconds)
Here a 100 milli seconds delay is added after the commands, which allows for 10 changes to be detected per second at max.

void loop() {

	pot.tick();
	if (pot.hasChanged()) {
		printf("current value: %d\n", pot.getValue());
	}
	delay(100);
}

This works well, but using delay has one drawback that may not be immediately obvious here. delay() will stop the CPU from doing anything during the delay period. So if you want other stuff to be done as well, this also by consequence is stopped for the duration of the delay time. Have a look at this example of using delay and some other function.

void doSomeOtherStuff() {
	printf("I'm doing other stuff now\n");
}

void loop() {
	int value = 0;

	pot.tick();
	if (pot.hasChanged()) {
		value = pot.getValue();
		printf("current value: %d\n", value);
	}
	delay(100);
	doSomeOtherStuff();
}

Method two: use a counter
Increment the static counter each loop and whenever this reaches a large number, check the pot, otherwise skip checking the pot and continue with the rest of the code.

#define DELAY_CNT 1000000

void doSomeOtherStuff() {
	printf("I'm doing other stuff now\n");
}

void loop() {
	static int cnt = 0;
	int value = 0;

	if ((cnt % DELAY_CNT) == 0) {
		pot.tick();
		if (pot.hasChanged()) {
			value = pot.getValue();
			printf("current value: %d\n", value);
		}
	}
	cnt += 1;
	doSomeOtherStuff();
}

The static counter cnt will keep its value whenever the loop is repeated, so we can use this to count to a large number before we tick the pot. Because we initialize cnt to 0 the pot is checked right away because (0 % DELAY_CNT) will evaluate to 0. If you do not want this to happen on the first run, simply initialize cnt to 1. Then it will take (DELAY_CNT - 1) loops before the pot is ticked. The code ((cnt % DELAY_CNT) == 0) does a so called modulo division. (cnt % DELAY_CNT) will return 0 whenever cnt is a multiple of DELAY_CNT and otherwise it will return cnt. The code ((cnt % DELAY_CNT) == 0) does a so called modulo division.
Because doSomeOtherStuff() is outside of the if-statement that deals with the value of cnt, this subroutine is called every time the loop repeats while the pot is only checked every DELAY_CNT times the loop restarts.

To recap, here is the whole program once more:


// example program 2

// Include libprintf which makes printing to the serial port SOOOO much easier.

#include <LibPrintf.h>

// Include the potentiometer class
#include "Potentiometer.hpp"

// Here are some constants and global variables (beware of the latter!).
#define ANA_IN_PIN A0
#define SERIAL_SPEED 312500
#define DELAY_CNT 1000000

Potentiometer pot;

void doSomeOtherStuff() {
	printf("I'm doing other stuff now\n");
}

void setup() {
 	Serial.begin(SERIAL_SPEED);
	// Instantiate the potentiometer and link it to an analog input.
 	pot = Potentiometer(ANA_IN_PIN);
}

void loop() {
	static int cnt = 0;
	int value = 0;

	if ((cnt % DELAY_CNT) == 0) {
		pot.tick();
		if (pot.hasChanged()) {
			value = pot.getValue();
			printf("current value: %d\n", value);
		}
	}
	cnt += 1;
	doSomeOtherStuff();
}

If you run the loop containing the delay and compare that to the loop containing the cnt, you will see that the former will run the doSomeOtherStuff() much less frequently than the latter. You will find a usable value for DELAY_CNT by experimenting with a few values.

Let’s have a look at the Potentiometer class now. This bundles all the functions we need for the potentiometer in one place. This is the content of the file Potentiometer.hpp

#ifndef _POTENTIOMETER
#define _POTENTIOMETER

class Potentiometer {

    private:

        int  pinNr;
        int  currentPotValue = 0;
        int  oldPotValue = -1;
        int  errorValue = 5;
        bool valueHasChanged = false;

    public:

        Potentiometer() {};

        Potentiometer(int pin_nr) {
            pinNr = pin_nr;
        }

        void tick() {
            // Read and update pot value,
            int newPotValue = analogRead(pinNr);
            if (abs((oldPotValue - newPotValue)) >= errorValue) {
                currentPotValue = newPotValue;
                oldPotValue = newPotValue;
                valueHasChanged = true;
            }
        }

        bool hasChanged() { // Has the value changed since checked last time?
            bool returnValue = valueHasChanged;
            valueHasChanged = false;
            return(returnValue);
        }

        int getValue() { // Get the current value of the potentiometer.
            return(currentPotValue);
        }
};

#endif

The nice thing about using a class is, that it bundles the whole functionality of the potentiometer in one place. Whenever we need to change something about the potentiometer, we can do this in the class and often leave the main program parts setup() and loop() untouched. Furthermore there are no variables in the loop() and setup() that could implicitely affect the potentiometer once it is initialized. So we do not need to worry about side effects which cause programs to misbehave. Global variables (they are the PITS!) often are the source of problems. The only thing we need to remember is to tick the pot now and then.
Especially when using external devices like ADC or analog switches or multiplexers etc in my programs, I’ve found that doing that part of the programming the C++ way (making a class for them) makes the software more modular, more readable and easier to debug. And writing general classes makes it easier to reuse code you built, tried and found to work to your liking in new projects.

The class contains some private variables. They are not directly accessible from the outside. They are used to keep track of the state of the potentiometer. The public functions (also called methods) are the ones you as a user can use to query (and sometimes set) the state of the class.

The Potentiometer class contains a getValue() function. This does not read the analog value from the ANA_IN_PIN immediately but just returns the variable current_value that was updated by the tick() function. The tick function reads the analog value as an integer number. Given a 12 bit AD-converter this value will vary from 0 to 1023. Tick stores the newly read value in currentPotValue whenever this value differs from the prior value (oldPotValue) by a certain errorValue. Once there is a large enough difference (the function abs() makes that a higher or lower value will do) the boolean valueHasChanged will be set to true.
Often in a program we only want to do something if the user changed some value of the controls so we want the program to be able to check whether something has changed. The function hasChanged() will tell us whether this is the case. Obviously the boolean has to be reset after a change and this could be done whenever the value is read, or whenever the boolean status is queried. I’ve chosen for the latter. So, as soon as if(pot.hasChanged()) is executed we find out that the boolean is true or false and when true it is set to false immediately. in that way the class does its own book keeping.

What is this #ifndef _POTENTIOMETER #define _POTENTIOMETER #endif at the beginning and end of the file containing the class all about?, you may ask.

The Potentiometer.hpp needs to be included in the main program.
Especially if the program grows in complexity and there are other classes which are included in the main program that themselves may include Potentiometer.hpp as well, we run the risk of including it multiple times. That may in some cases lead to problems when compiling the code (classes would appear to be defined multiple times). It is good practise to exclude this from happening by adding the #ifndef constructs to each .hpp file. Typically for the define a name is used that is not likely to be found elsewhere in your program so often a underscore is added to the class name. The #define _POTENTIOMETER will prevent a second inclusion of the code.

What is the errorValue all about? Analog inputs may sometimes pick up some noise. If you do not want this to be seen as a change of the pot value, the errorValue will help to ignore the noise. Only if the change is large enough, the valuehasChanged boolean will be set. I emperically found that 5 is ok. Note that the errorValue introduces what is also called hysteresis.

If in your program, you use more potentiometers, the advantage of using a class is that each pot gets its own object. Each object keeps track of its own current and old value. You do not need to add any additional code for this. Just remember to tick each pot once in a while in the main loop! In the next example you find 2 potentiometers being used.


// example program 3

// Include libprintf which makes printing to the serial port SOOOO much easier.

#include <LibPrintf.h>

// Include the potentiometer class
#include "Potentiometer.hpp"

// Here are some constants and global variables (beware of the latter!).
#define ANA_IN1_PIN A0
#define ANA_IN2_PIN A1
#define SERIAL_SPEED 312500
#define DELAY_CNT 1000000

Potentiometer pot1;
Potentiometer pot2;

void doSomeOtherStuff() {
	printf("I'm doing other stuff now.\n");
}

void setup() {
 	Serial.begin(SERIAL_SPEED);
	// We instantiate the potentiometers and link them to an analog input.
 	pot1 = Potentiometer(ANA_IN1_PIN);
 	pot2 = Potentiometer(ANA_IN2_PIN);
}

void loop() {
	static int cnt = 0;
	int value = 0;

	if ((cnt % DELAY_CNT) == 0) {
		pot1.tick();
		if (pot1.hasChanged()) {
			value = pot1.getValue();
			printf("current value of pot 1: %d\n", value);
		}
		pot2.tick();
		if (pot2.hasChanged()) {
			value = pot2.getValue();
			printf("current value of pot 2: %d\n", value);
		}
	}
	cnt += 1;
	doSomeOtherStuff();
}

To run any of the code, you may need to install LibPrintf using the library manager of the arduino IDE.

I’ve made some derived classes that implement a potentiometer with a zero center value, a potentiometer that is quantized so that it will only return one of e.g. 5 values. This can come in handy if you want to use a potentiometer as a control of the menu system of a device and make a choice out of a discrete number. These other potentiometers are based on the one presented here. In fact they inherit its base functionality and add some more functions. I will leave these code snippets for another post.

For those who want to comment on the examples, remember, this is not stackoverflow.com, most of us are not computer scientists, so BEHAVE !

5 Likes

In my earlier posts I spoke of deriving sub classes. One example I’ve used in a project is that of a zero centered potentiometer. With this I mean a potentiometer that will provide a negative value when turned left past ist center position, return a zero value when in center position and a positive value when turned to the right past its center position. So e.g. it will result in values -512 … 0 … 512 withy a 10 bit dac when turned from all the way left via the center position all the wayt to the right.

One way of achieving this with the existing code is to get the value of the potentiometer and scale it.

// example program 4

// Include libprintf which makes printing to the serial port SOOOO much easier.

#include <LibPrintf.h>

// Include the potentiometer class
#include "Potentiometer.hpp"

// Here are some constants and global variables (beware of the latter!).
#define ANA_IN_PIN A0
#define SERIAL_SPEED 312500
#define DAC_RESOLUTION 1024 // In case of a 10 bit DAC

Potentiometer pot;

void setup() {
 Serial.begin(SERIAL_SPEED);
 // We instantiate the potentiometer and link it to an analog input.
 pot = Potentiometer(ANA_IN_PIN);
}

void loop() {

	pot.tick();

	if (pot.hasChanged()) {
		int value = pot.getValue()  - DAC_RESOLUTION / 2;
		printf("new value: %d\n", value);
	}
}

But we can also using the C++ principle of inheritance define a second type of potentiometer called ZeroCenterPotentiometer that inherits all functions from the Potentiometer class but which has its own version of the getValue function. Let’s assume this new class is stored in ZeroCenterPotentiometer.hpp like this:

#ifndef _ZEROCENTERPOTENTIOMETER
#define _ZEROCENTERPOTENTIOMETER

#include "Potentiometer.hpp"

class ZeroCenterPotentiometer: public Potentiometer {
  
  #define DAC_RESOLUTION 1024 // In case of a 10 bit dac
  
  public:

    ZeroCenterPotentiometer() {}
    ~ZeroCenterPotentiometer() {}

    ZeroCenterPotentiometer(int pin_nr) : Potentiometer(pin_nr) {}
    
    int getValue() {
      int newValue = Potentiometer::getValue() - DAC_RESOLUTION / 2;
      return(newValue);
    }
};

#endif

We need to include Potentiometer.hpp otherwise the compiler and linker do not know which definition of Potentiometer is meant in the constructor of the ZeroCenterPotentiometer.

To be able to work, the ZeroCenterPotentiometer class has to provide the pin number of the analog input to the Potentiometer class. This is done via Potentiometer(pin_nr) in the constructor definition. In its own version of getValue(), the ZeroCenterPotentiometer class uses Potentiometer::getValue() to call the getValue op the parent Potentiometer class. The value is then scaled and stored in newValue. Calling zeroCenterPotentiometer.getValue() will return this scaled value.

One of the advantage of using a new class in stead of a simple scaling function is that in the main code all potentiometers are treated alike. All present a value when their getValue function is called. Given that the scaling is done within the class as a programmer you do not need to worry about scaling the value, this is done automagically.
Note: in the ZeroCenterPotentiometer class we do not have to implement a tick() and a hasChanged() function. They are inherited from the Potentiometer class definition!

You can place the new class in its own file ‘ZeroCenterPotentiometer.hpp’ and include that in the src-file that contains the loop-function (but you are free to put all the potentiometer classes in one file and only include that):

// example program 5

// Include libprintf which makes printing to the serial port SOOOO much easier.

#include <LibPrintf.h>

// Include the potentiometer classes
#include "Potentiometer.hpp"
#include "ZeroCenterPotentiometer.hpp"

// Here are some constants and global variables (beware of the latter!).
#define ANA_IN_PIN_1 A0
#define ANA_IN_PIN_2 A1
#define SERIAL_SPEED 312500

Potentiometer pot1;
ZeroCenterPotentiometer pot2;

void setup() {
 Serial.begin(SERIAL_SPEED);
 // We instantiate 2 potentiometer and link each to an analog input.
 pot1 = Potentiometer(ANA_IN_PIN_1);
 pot2 = ZeroCenterPotentiometer(ANA_IN_PIN_2);
}

void loop() {

	pot1.tick();
	pot2.tick();

	if (pot1.hasChanged()) {
		printf("current value of pot 1: %d\n", pot1.getValue());
	}
	if (pot2.hasChanged()) {
		printf("current value of pot 2: %d\n", pot2.getValue());
	}
}

Although in ZeroCenterPotentiometer we have not explicitely defined tick() and hasChanged() functions, because they are inherited from Potentiometer class, we can also call then from pot2.

Note: adding #include “Potentiometer.hpp” here is not strictly necessary as this include statement also is present in ZeroCenterPotentiometer.hpp, so it is added already, but I’ve added it here anyway for clarity.

4 Likes

Combining 2 software modules

I built the Clock Multiplier published by www.bummbummgarage.com
and found that their Random Trigger module will run on the same hardware, which is based on an arduino nano.

Instead of building two separate devices, I decided to try and merge the two.

Since they have their own software which in some parts is the same, I thought, why not put the common denominator code in the main loop and/or setup routine and implement the rest as 2 objects where the button on the module gets an extra function allowing to switch between the Clock Multiplier and the Random Trigger module.

So I adapted the original C-code by converting it into C++ classes, and merged the setup parts of the two modules into one. Both main-loops I refashioned into tick functions as described in my earlier posts.
Converting the C-code to C++ code may sound complicated, but if you compare the original C-code to the C++ code, you can see that I’ve merely enclosed the original code in a class MyClass {}; statement and added a constructor definition. That’s more or less all I had to do to get things working.

I used the OneButton library for responding to button pushes.

So in a stylized way the main program looks something like this:

#include "OneButton.h"
#include "ClockMultiplier.hpp"
#include "RandomTriggers.hpp"

bool inClockMultiplierMode = true;

// instantiate the objects that contain the module functions

ClockMultiplier clockMultiplier =
  ClockMultiplier(triggerInPin,
                  triggerInLEDPin,
                  quantityPotiPin,
                  quantityCVPin,
                  distributionPotiPin,
                  triggerOutLEDPin,
                  triggerOutPin);


RandomTriggers randomTriggers =
  RandomTriggers(triggerInLEDPin,
                 triggerInPin,
                 densitiyPotiPin,
                 lengthPotiPin,
                 triggerOutLEDPin,
                 triggerOutPin);

OneButton button(toggleAndMutePin, false);

// When double clicked we change from Clock Multiplier to Random Trigger generator.
void doubleClickCallBack() {
  inClockMultiplierMode = !inClockMultiplierMode;
  updateModeLeds();
}

// When the button is pressed 1 time we toggle the mute state, this is for the Clock Multiplier only.
void singleClickCallback() {
  if (inClockMultiplierMode) {
    inMutedState = !inMutedState;
  }
} 

void setup() {

  // initialize all input and outputs
  pinMode(triggerInPin, INPUT);
  pinMode(triggerInLEDPin, OUTPUT);
  pinMode(quantityPotiPin, INPUT);
  pinMode(quantityCVPin, INPUT);

  etc. etc..

  // Link some callback functions to the button
  button.attachClick(singleClickCallback);
  button.attachDoubleClick(doubleClickCallBack);
}

So I ended up with a very simple main loop function:

void loop() {
  if (inClockMultiplierMode == CLOCK_MULTIPLIER) {
    clockMultiplier.tick(inMutedState);
  } else {
   randomTriggers.tick();
  }
  button.tick();
}

The tick-functions are called as often as possible so that the ClockMultiplier, RandomTrigger and Button objects can do whatever it is they need to do. The timing of these functions is left to these objects.

You can find the code on my github.

4 Likes