Random number generator (Part 2)

Part 1, 2, 3

Here is a noisy signal sampled at 100 kHz with an Arduino UNO. The signal has 8 bits of resolution and the divider bridge of the final amplifying stage has been set so that the ADC range matches (without exceeding) the input signal range. Here is the illustration of a vector of 1024 data points sampled from the noise generator.


You may want to download these data in order to perform your own analysis, and I would be more than happy to publish your own results.

Firstly, let’s look at the distribution of data points versus their mean value. To do so, we compute the probability mass function:


This result is typical from thermal noise. The distribution of the number of data points from each bin looks like a Gaussian distribution. Starting from there it is possible to apply envelope modelers in order to get an overall picture of the distribution. Running an Hilbert transform might overwhelm our arduino UNO so I applied a simplified algorithm which gives pretty good results.


Now we know that we are really measuring what we expect. Let see if this signal is not contaminated by other signals… To do so, we apply a FFT in order to detect the possible presence of signals characterized by individualized frequencies (and possibly their harmonics) having significant strength (signal to noise ratio). Next is the frequency spectrum from the test signal:


Well, at first glance, there is nothing special to say about it. Is there something near 8 kHz ? Running this test on multiple vectors of data does not confirm this hypothesis. Running the test on extra large vectors of data would bring us to some sort of flat spectrum.

An other interesting analysis tool is the Phase Portrait. Here is a plot of the phase portrait applied to the test data. The spot is centered on the 0;0 coordinate and no repeated trend line shows up from the plot, meaning that we are dealing with real white noise.


Here and there are very good examples of phase portraits applied to clean and noisy signals.

Next post on same subject

Random number generator (Part 1)

Part 1, 2, 3

As I was stumbling the web looking for advanced information on thermal noise, I found some very interesting papers on RNGs, aka Random Number Generators. These devices feature hardware components which are responsible for a generating unpredictable random numbers !

This is a very interesting matter as it involves physics, electronics, mathematics, software and … ultimately cryptography. Credit is due to people smarter than I am which publications can be found at the end of this post. The idea here is to described a surprisingly simple and yet powerful method for generating random numbers of various length, actually from 1 to 32 bits.

The principle of operation relys on the amplification of the signal produced on the base of a reverse-biased transistor. The emitter is saturated with electrons and occasionally they will “tunnel” through the band gap and exit via the base. This signal is then amplified through two transistors one of them behind biased through a decoupling capacitor in order to get rid of the DC component of the signal.

Here is the electronic section of the project: All you need is a trio of general purpose NPN transistors such as the popular 2N3904 a pair of capacitor and few resistors. The schematic is rather simple.


I brought a little refinement to the original design by feeding the amplifying stage with a stable +5 V. Note that both Vin and +5 V should be decoupled by 10 µF capacitors (Watch out the operating voltage of the capacitor attached to Vin !). Under these conditions, the circuit outputs a 0 to 1  V signal which fits very well the analog to digital conversion using the 1.1  V internal reference. Please note that 5 V will not suffice to create a reverse bias condition on the base-emetter junction of T1. I managed to get a stable running state starting with Vin = 9 V.


I also brought few refinements to the original code originally written by Rob Seward (v1.0 dated 4/20/2009 ). Firstly, the analog read function is replaced by a custom one which is way faster, thanks to its 8 bits resolution, low prescaler and refined code. the SetADC() function must be inserted within the setup() part of the code

/* Set adc parameters for 8 bits resolution, fast mode */
void SetADC(uint8_t adcChannel) 
	/* Clear ADC control registers */
	ADCSRA = 0x00;
	ADCSRB = 0x00;
	ADMUX  = 0x00;
	// ADMUX |= (1 << REFS0); /* DEFAULT 5 V*/
	ADMUX |= (1 << REFS1) | (1 << REFS0); /* INTERNAL 1.1 V */
	ADMUX |= adcChannel; /* Set channel */
	ADMUX |= (1 << ADLAR); /* Left align adc value, so as to say 8 bits resolution */
	ADCSRA |= 3; /* Set ADC prescaler */
	ADCSRA |= (1 << ADEN); /* Enable ADC */
	ReadADC(); /* Run one mock read */

inline uint8_t ReadADC(void) 
	const uint8_t ADSCmask = (1 << ADSC);
	/* Start conversion */
	ADCSRA |= ADSCmask; 
	/* Wait for conversion */
	while (ADCSRA & ADSCmask);
	/* Read digital value */
	uint8_t result = ADCH;
	/* Returned value */

Please note that in spite of its higher sampling rate capacity (about 100 kHz), we are still far from optimal sampling rate (1 Mhz or better). However, that will be enough for an experiment.

I also brought few refinements to the application specific functions:

/* Porcess the input value, so as to say the adc reading */
void ProcessInput(uint8_t adcValue)
	/* Set default value */
	uint8_t input = 0;
	if (adcValue > _adcThreshold) {
		input = 1;
	case EXC_OR:

/* Apply exclusive or to pairs of bits (thanks to the flip flop flag) */
void ExclusiveOr(uint8_t input)
	static uint8_t flipFlop = 0;
	static uint8_t previousInput = 0;
	if (flipFlop) {
		BuildRandomNumber(previousInput ^ input);
	previousInput = input;
	flipFlop = !flipFlop;

/* Apply Von Neumann to pairs of bits (thanks to the flip flop flag) */
void VonNeumann(uint8_t input)
	static uint8_t flipFlop = 0;
	static uint8_t previousInput = 0;
	if (flipFlop) {
		if (input & ~previousInput){
		} else if (~input & previousInput){
	previousInput = input;
	flipFlop = !flipFlop;

/* Append new bit to the currently built random number */
void BuildRandomNumber(uint8_t input)
	/* Shift previous bits */
	_outputBuffer <<= 1UL;
	/* Append input bit as LSB */
	_outputBuffer |= (input & 0x01);
	/* Update bits counter */
	_bitsCounter += 1;
	if (_bitsCounter == _outputBits) {
		/* Reset bytes counter */
		_bitsCounter = 0;
		/* Output data */
		_mainCounter += 1;
		Serial.print(_mainCounter, DEC);
		case BINARY:
			Serial.print(_outputBuffer, BIN); 
		case DECIMAL:
			Serial.print(_outputBuffer, DEC);
			Serial.print(_outputBuffer, HEX);
		_outputBuffer = 0x00;

/* Record occurences of adc values in their corresponding bins */
void SortAdcValue(uint8_t byteValue)
	/* Update occurences counter of the current adc vlaue */
	_vSorter[byteValue] += 1; 
	/* Update counter of sorted values */
	_sortedValuesCounter += 1;

Compute the adc threshold which is the median of the counts of occurences for 
each adc value void 
void ComputeAdcThreshold(void)
	uint32_t sum = 0;
	/* Compute the sum of adc occurences in all bins */
	for (uint16_t i = 0; i < _sorterSize; i++){
		sum += _vSorter[i];
	/* Compute half the sum of all observations */
	uint32_t halfSum = (sum >> 1);
	/* Reset sum */
	sum = 0;
	/* Find the adc value corresponding to half the sum of occurences */
	_adcThreshold = 0;
	while (sum < halfSum) {
		sum += _vSorter[_adcThreshold];
		_adcThreshold += 1;

This is how the code was looking like when I performed early tests which were not so bad in the end !

Next picture illustrates the probability mass function (aka pmf) from 65536 random numbers ranging from 0 to 65535:


As you can see, the spectrum is pretty homogeneous, showing a fine spreading of random numbers over the expected range. Next is the FFT from the raw data:


Once again, the spectrum is pretty homogeneous, showing no particular recurring pattern. Additional statistics show an average value of 32711.29 which turns to a -0.17 % error. The skewness (symetry of data versus average) is 0.003. All these statistics are very encouraging. However, I might have a use the Dieharder, “A Random Number Test Suite” which looks it is the perfect tool for checking randomness of numbers.

Next steps ? I think that I will pack this material in a library (Why not PlainRNG ?) and run some long term testing…


Next post on same subject

Trick of the day

This is a funny although very serious one: When you are looking for something very special, pretty complex such as papers on thermodynamics, astronomy, advanced electronics, etc. and you fail to find some information of interest, just insert the “arduino” word to your sequence of searched words.

From my own experience, the chances of finding the information of interest jumps to 90%.

Hum, great, just great  will you say, but “what about the 10% cases when it fails ?”

Well, the information found in these “failing” cases might just strike you as it did recently. I am more and more amazed by what the people manage to get from this insignificantly slow, rough, cheap piece of glass and silicon called arduino.


Much more than just a piece of hardware and a bunch of lines of code, this is an awesome concept and the common denominator for a whole social network of makers. Long live arduino !

The word of the day …

Thank you Michel, a senior professor in economy with which we had a pleasant time last Sunday, for talking about Jugaad during talks about news paradigms in many domains.

I like very much this concept, and I ought to spend more time with Dr. Shiv Parakash Rathnam (alias Dr. Shiv) talking about this principle that I realize now he had in mind while we were sharing experiences about R&D.

This principle is very complementary to the Occam’s razor principle (aka law of parsimony) and adds the dimension of frugality which is very common in the world of Fab Labs or even startups.

Some time ago, I heard about the Foldscope (so amazing) without understanging that this was a perfect example of the Jugaad


Did you apply Jugaad recently ? I am looking forward to reading your comments soon !

Ultrasonic scanner (Part 2)

Part 1, 2

Most of the electronic diagram shown here should look familiar to the readers of arduinoos posts. The ultrasonic sensor is added to what was described as the test bench for stepper motors.


Here is the list of the required components:

  • An Arduino UNO baord (Should I introduce it to you ?)
    • A bread board featuring a switching voltage regulator
    • A stepper motor driver (in this case a A4988)
  • A stepper motor (Cheap 5 V, 1024 steps per turn stepper motor)
  • A 3D printed base plate and a 3D printed wheel
  • A 12 V DC power supply which current rating is compatible with the stepper motor (Do  not expect to feed the stepper through the USB 5 V!)
  • A HC-SR04 ultrasonic sensor.

Running the whole assembly requires some lines of code. This code features specific commands for the HC-SR04: any working library will do the job. The rest is a mix of stepper motor driving functions and some maths.

Next is an extract from the header section of the sketch:

/* Create objects */
/* Change parameters according to hardware configuration */
PlainHCSR04 SONAR; /* Create an instance of the SONAR object */
const uint32_t _oneSecond = 1000000; /* In us */
uint16_t _frequency = 500; /* Rotational speed */
const uint8_t _pulseDelay = 1; /* In us */
const uint16_t _motorStepsPerRound = 1024;
const float _sweepRad = (TWO_PI / 1.0); 
const float _sweepRadResolution = (TWO_PI / 90.0); 
const uint16_t _motorStepsPerSweepStep = uint16_t((_motorStepsPerRound * _sweepRadResolution) / TWO_PI);
const uint8_t _ultraSoundSensorSamples = 4;
const uint16_t _stabilizationDelay = 10; /* In ms */
/* Direction port and pin */
volatile uint8_t *_dirCtrlPort = &PORTB;
const uint8_t _directionPinMask = (1 << PINB0);
/* Pulse port and pin */
volatile uint8_t *_stepCtrlPort = &PORTB;
const uint8_t _stepPinMask = ( 1 << PINB1);  
/* Enable port and pin */
volatile uint8_t *_enablePort = &PORTB;
const uint8_t _enablePinMask = ( 1 << PINB2);  

Check some of the critical variables:

  • _frequency set the rotational speed
  • _motorStepsPerRound defines the number of steps per round (1024 in my case)
  • _sweepRad defines the full rotational swing for each scan
  • _sweepRadResolution defines the rotational angle between two distance measurements
  • _ultraSoundSensorSamples defines the number of samples acquired for each distance measurements: the more samples the better the accuracy, the longer the measurement time

The set section initializes the ultrasonic sensor and the stepper motor driver:

void setup(void) 
	SONAR.HCSR04Initialization(&PORTD, 6, 7);
	/* Set direction ports and pins */
	*(_enablePort - 1) |= _enablePinMask; /* EnableStepper pin */
	*(_enablePort) |= _enablePinMask; /* Disable driver */
	*(_dirCtrlPort - 1) |= _directionPinMask;
	*(_dirCtrlPort) |= _directionPinMask; /* Set default direction */
	*(_stepCtrlPort - 1) |= _stepPinMask; /* Set pin direction */
	*(_stepCtrlPort) &= ~_stepPinMask; /* Set default pin state to LOW */	
	while(Serial.available()) {
		Serial.read(); /* Empty buffer */

And here is the loop section which is executed any time any character is entered on the console. The console outputs the data acquired during a whole scan:

void loop(void) 
	if (Serial.available()) {
		while(Serial.available()) {
			Serial.read(); /* Empty buffer */
		float totalSweepRad = 0.0;
		uint16_t sweepSteps = 0;
		/* Sweep forward */
		do {
			/* Wait for stabilization before acquiring data */
			/* Acquire distance */
			float distance = (SONAR.Distance(_ultraSoundSensorSamples) / 1000.0);
			/* Rotate stepper forward to next sub division */
			RotateStepper(1, _motorStepsPerSweepStep);
			/* Compute angle and cartesian coordinates */
			float x = (sin(totalSweepRad) * distance);
			float y = (cos(totalSweepRad) * distance);
			/* Upload data */
			Serial.print(totalSweepRad, 3);
			Serial.print(distance, 3);
			Serial.print(x, 3);
			Serial.print(y, 3);
			/* Update variables */
			sweepSteps += 1;
			totalSweepRad = (_sweepRadResolution * sweepSteps);
		} while (totalSweepRad <= _sweepRad);
		/* Sweep back */
		RotateStepper(0, (_motorStepsPerSweepStep * sweepSteps));

The console will output fields delimited with a semi-colon. The first field contains the measurement index. Next two fields are the polar coordinates (angle and distance) while the newt two fields contain the Cartesian coordinates (so as to say x and y). In this way, it is easy to build a graph out of the acquired data such as this one, using any spreadsheet editor:


Enjoy !



Ultrasonic scanner (Part 1)

Part 1, 2

And now, something completely different : here is arduinoos’s ultrasonic scanner !


This ultrasonic scanner results from the combination of two main components: an ultrasonic sensor and a stepper motor. Both have already been covered in this blog (here and there).



Both component form the head of the scanner which is screwed on top of a basic camera tripod thanks to additional mechatronic components.

These components are very popular and available at cheap prices on the web or straight from your scrap box. An Arduino platform, a voltage regulator and a stepper-motor driver are also required. Once again these are pretty cheap components that you may already have. Both the voltage regulator and the stepper motor driver will be plugged onto a bread board.


Both the arduino board and the bread board sit in a custom shell which fits to the stands of the tripod thanks to a pair of clips…


The principle of operation of this ultrasonic scanner is rather simple. The ultrasonic sensor is mounted directly on top of the shaft of the stepper motor. On each step pulsed to the stepper motor, the ultrasonic sensor performs one (or more) measurements. So that on each completed step, the scanner exports an angular value and a distance. Applying some math results in exporting x and y coordinates too. These data can be used to reconstruct an image of the solid objects surrounding the scanner.


As the stepper that I choose features 1024 steps, the code will manage to set larger angular resolution that the user may change according to his needs. Same for the full swing of the scan, the user may decide to sweep any range from 0 to 360°.

Although this scanner looks like it has been designed for building maps, it can be used for  measuring the actual sonic beam of the sensor too.

Next post on same subject


Publication of the day

Raymond McNamara from the NUI Galway committed his final year works to “Embedded Implementation of Embedded Algorithms of Power System Monitoring”

Raymond McNamara report

Quality of AC power is definitely a contemporary problem. Many disturbances are generated by the variety of power sources including, and the list is non-exhaustive, solar power, wind power, hydroelectric power. Harmonic frequencies in the power grid are a frequent cause of power quality problems. Harmonics in power systems result in increased heating in the equipment and conductors, misfiring in variable speed drives, and torque pulsations in motors. They may even lead to massive power failures on main distribution lines. So that power distributors have a great concern for analyzing these disturbances. and thus the need for advanced studies. Raymond’s work s about analyzing these disturbances and has been kind enough to mention arduinoos publications in his References section. Thanks Raymond.

You can get Raymond’s report >here<

Stepper Motors (Part 7)

Part 12, 3, 4, 5, 6, 7

This post is about driving stepper motors. In the previous posts I described the various components involved in motorized assemblies featuring stepper motors. However, putting all these nuts and bolts together may lead to unexpected results. In my case, these defects where related to the use of stepper motors taken from my scrap box, most of them lacking clear identification or appropriate specifications. Thus the need for building a test bench for testing these motors and giving them a chance to leave a second life !

Next picture illustrates the test bench which is made of (starting from right to left):

  • An Arduino UNO baord (Should I introduce it to you ?)
    • A bread board featuring a switching voltage regulator
    • A stepper motor driver (in this case a A4988)
  • A stepper motor (Cheap 5 V, 2048 steps per turn stepper motor)
  • A 3D printed base plate and a 3D printed wheel
  • A 12 V DC power supply which current rating is compatible with the stepper motor (Do  not expect to feed the stepper through the USB 5 V!)


Next picture illustrates the wiring diagram.


After multiple attempts to run stepper motors from my scrap box, I realized how critical might be the voltage applied to the stepper through its driver. Too much voltage leads to excessive magnetic fields and unpredictable motions at certain frequencies (f = 1 / time_between_2_consecutive_pulses_applied_to_the_driver); excessive voltage also drives to motor overheating. So that this test bench features a well known, cheap and yet powerful voltage regulator. This is precisely a “buck” switching regulator, “buck” means that it lowers the input voltage (as opposed to “boost”) and switching means that a MOSFET transistor acts as a fast on-off electronic tap which leaves a known amount of current flowing from the input to the output of the module. The benefit from such design (switching regulator) is the low power dissipation across the switch at even pretty high current (up to 3 A for this module). These modules are available for a few €/$, some of them  feature a voltage display which might be convenient for those who lack measuring instrumentation.


Next is an also well known module. The A4988 contains all the bits and pieces necessary for driving almost any stepper motor (please check previous posts on same topic). In this configuration, three out of the multiple configuration pins are used: Enable, Step and Direction. These pin are connected to any port and pin from an Arduino UNO board (or compatible)


The test bench is driven by a quite simple application which uses the Arduino’s IDE console as a Human Interface. The list of available commands is available at run time after typing the “?” character. In this list, the available range for the arguments as well as the actual values are printed, offering one sort of a dashboard to the user.


	Stepper motor test bench, Arduino UNO compatible
	Copyright (C) 2016 Didier Longueville

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	KEYWORDS: stepper motor, A4988, enable, direction, frequency, step, pulse

/* Direction port and pin */
volatile uint8_t *_dirCtrlPort = &PORTB;
const uint8_t _directionPinMask = (1 << PINB0);
/* Step port and pin */
volatile uint8_t *_stepCtrlPort = &PORTB;
const uint8_t _stepPinMask = ( 1 << PINB1);  
/* Enable port and pin */
volatile uint8_t *_enablePort = &PORTB;
const uint8_t _enablePinMask = ( 1 << PINB2);  
/* Variables and constants */
const uint32_t _oneSecond = 1000000; /* In us */
uint32_t _interval = 0;
uint32_t _lastStepTime;
uint16_t _frequency;
const uint8_t _pulseDelay = 1; /* In micros */
uint32_t _pulseCounter;
uint32_t _pulses = 0;
uint16_t _argument;
uint8_t _opcode;
uint8_t _enabled;
uint8_t _direction;
uint8_t _running;

void CommandProcessor(void) 
	if (Serial.available()) {
		while (Serial.available()) {
			char inputChar = Serial.read();
			if (inputChar == 0x3F) {
				_opcode = 0;
			} else if ((inputChar >= 0x41) && (inputChar <= 0x5A)) { /* Alpha character */
				/* Probably an _opcode */
				_opcode = uint8_t( inputChar);
			} else if ((inputChar >= 0x30) && (inputChar <= 0x39) && (_opcode != 0)) { /* Num character */
				_argument *= 10; /* Exponent previous value */
				_argument += uint8_t(inputChar - 48); /* Add currrent value */
			} else if ((inputChar = 0x0A) || (inputChar = 0x0D)){ /* Cr Nl */
				switch (_opcode) {
				case 'D': /* Direction */
					_direction = _argument;
					if (_direction == 0) {
						*(_dirCtrlPort) &= ~_directionPinMask;
					} else if (_direction == 1) {
						*(_dirCtrlPort) |= _directionPinMask;
				case 'E': /* Enabled */
					_enabled = _argument;
					if (_enabled == 0) {
						*(_enablePort) |= _enablePinMask;
					} else if (_enabled == 1) {
						*(_enablePort) &= ~_enablePinMask;
				case 'F': /* Frequency */
					_frequency = _argument;
					_interval = (_oneSecond / _frequency); /* Compute interval */
					_lastStepTime = micros();
				case 'I': /* Intervals */
					_interval = _argument;
					_frequency = (_oneSecond / _interval); /* Compute frequency */
					_lastStepTime = micros();
				case 'P': /* Pulses */
					_pulseCounter = 0;
					_pulses = _argument;
				case 'R': /* running state */
					_running = _argument; 
				if (_opcode) {
					Serial.print(" : ");
				_opcode = 0; /* Reset opcode */
				_argument = 0; /* reset argument */

void PrintCommands(void)
	Serial.print(F("D [0:1]: direction ("));
	Serial.print(F("E [0:1]: enable ("));
	Serial.print(F("F [1:32767]: frequency in Hz ("));
	Serial.print(F("I [1:65535]: interval in us ("));
	Serial.print(F("P [0:65535]: pulses and then idle, 0=infinite pulses ("));
	Serial.print(F("R [0:1]: running ("));
	Serial.print(F("? : help"));

void setup(void)
	/* Console for diag */
	/* Set direction ports and pins */
	*(_enablePort - 1) |= _enablePinMask; /* Enable pin */
	*(_enablePort) |= _enablePinMask; /* Disable driver */
	*(_dirCtrlPort - 1) |= _directionPinMask;
	*(_dirCtrlPort) |= _directionPinMask; /* Set default direction */
	*(_stepCtrlPort - 1) |= _stepPinMask; /* Set pin direction */
	*(_stepCtrlPort) &= ~_stepPinMask; /* Set default pin state to LOW */
	/* Compute default interval */
	_enabled = 0;
	_running = 0;
	_frequency = 100;
	_interval = (_oneSecond / _frequency);
	_lastStepTime = micros();

void loop(void)
	/* Send step pulse to the dirver */
	if ((micros() - _lastStepTime) > _interval) {
		_lastStepTime += _interval;
		if (_running) {
			Generate pulse: A low-to-high transition on the STEP input sequences 
			the translator and advances the motor one increment 
			*(_stepCtrlPort) |= _stepPinMask;
			*(_stepCtrlPort) &= ~_stepPinMask;
			/* */
			if (_pulses != 0) {
				_pulseCounter += 1;
				if (_pulseCounter >= _pulses) {
					_pulseCounter = 0; /* Reset counter */
					_running = 0; /* Reset running state */

Please note that running the stepper requires that the following steps are completed: set frequency or interval time as appropriate (default frequency is 100 Hz), enable the driver (“E1”) and set running state (“R1”). Why this distinction between enabling the driver and setting a running state ? When the driver is enabled and no pulses are sent, the stepper motor coils are still fed with some current. In this way, the rotor is locked in a rest position. As it is important to check this idle current both stages (enabled and running) are individualized.

It appeared to me that setting the most appropriate current limit required that multiple operating conditions had to be checked: setting various frequencies and checking the forward and reverse motion for example. The power supply voltage controller happened to be very useful for checking unmarked steppers and setting the optimal minimal voltage in order to decrease the dissipated temperature (almost none from the driver, most from the stepper motor itself).

Are you interested in the 3D printed base ? Get the .stl file >here<


User Interface (Part 5)

Part 1234, 5

I brought several improvements since the introduction of the early design of a simplified however yet powerful human interface. Among them the possibility to display variables that the user can change and variables or constants that the user cannot change. Thus the introduction of a new set of menu types:

/* Menu types */
const uint8_t MNU_TYP_HEADER = 0x00;
const uint8_t MNU_TYP_MOD_VALUE = 0x01;
const uint8_t MNU_TYP_FXD_VALUE = 0x02;
const uint8_t MNU_TYP_FLD_BACK = 0x03;

These new data types are the MNU_TYP_MOD_VALUE type  and the MNU_TYP_FXD_VALUE type.

The way the menuItem structure has been changed too in order to ease the readability of the whole menu structure. The new structure format looks like:

struct mnuItem { 
	uint8_t menuType; /* One of MNU_TYP_x */
	int16_t minValue; /* min value */
	int16_t maxValue; /* max value */
	uint8_t nextMenuIndex; /* Next menu item */
	uint8_t lastMenuIndex; /* Must be set to 0 as default */
	const char *ptrCap;  /* Pointer to menu ptrCap */


menuType: 	one of MNU_TYP_xxx,
minValue: 	min value (Base0), 
maxValue: 	max value (Base0),
nextMenuIndex: 	next sub menu index (Base0),
lastMenuIndex:	last menu index, for returning to previous level (Base0),
ptrCap: 	pointer to caption 

But the most significant change applies to the storage of arrays of characters (so as to say, strings). These memory consuming data are stored in the program memory instead of a storage in the SRAM. As their content keeps constant along the firmware usage, they are eligible to program memory storage. For your records, the SRAM memory is 2k wide in the UNO boards (featuring ATMEGA 328P micro-controllers) while the program memory is 32k wide, which is x16 times larger !

Storing and reading constant data in the program memory requires that the following steps are completed:

Declare pgmspace in the header section of the main code

#include <avr/pgmspace.h> /* Progmem */

Declare the arrays of characters in the header section: these are extracted from the unreleased MicroHTR application (heating element controller)

const char CAP_P_FIRMWARE[] PROGMEM =		"**  MicroHTR  **";
const char CAP_P_VERSION[] PROGMEM =		"    rev. 1a";
/* Application related constants */
const char CAP_P_SP[] PROGMEM = 		"SET POINT";
const char CAP_P_KP[] PROGMEM = 		"KP";
const char CAP_P_KI[] PROGMEM = 		"KI";
const char CAP_P_KD[] PROGMEM = 		"KD";
const char CAP_P_INT[] PROGMEM = 		"INTERVALS";
const char CAP_P_MAX_TEMP[] PROGMEM = 		"TEMP. MAX.";
const char CAP_P_MIN_TEMP[] PROGMEM = 		"TEMP. MIN.";
const char CAP_P_RESET[] PROGMEM = 		"RESET";
/* Captions, reserved words for menu driven interface (do not change) */
const char CAP_P_EXIT[] PROGMEM = 		"EXIT";
const char CAP_P_RETURN[] PROGMEM = 		"RETURN";


and here is the structure for the menu:

struct mnuItem vMnuItems[] =	
/* 	{type, 				min, 		max,		next,	last, 	caption}*/
	{MNU_TYP_HEADER,	X, 			X, 			X,		X,		CAP_P_FIRMWARE}, 				
	{MNU_TYP_HEADER,	0, 			3, 			2, 		X,		CAP_P_PARAM},
	{MNU_TYP_HEADER,	0, 			5, 			6, 		X, 		CAP_P_SETTINGS}, /* Main menu */
	{MNU_TYP_HEADER,	0, 			3, 			12,		X, 		CAP_P_STATISTICS},
	{MNU_TYP_HEADER,	0, 			1, 			16,		X, 		CAP_P_MISCELLANEOUS},
	{MNU_TYP_FLD_BACK, 	X, 			X, 			0,		X, 		CAP_P_EXIT},
	{MNU_TYP_MOD_VALUE,	MIN_SP,		MAX_SP,		2,		X, 		CAP_P_SP}, /* Settings */
	{MNU_TYP_FLD_BACK,	X, 			X, 			1, 		X, 		CAP_P_RETURN},
	{MNU_TYP_FXD_VALUE, MAX_TEMP, 	MIN_TEMP, 	3,		X, 		CAP_P_MIN_TEMP}, /* Statistics */
	{MNU_TYP_FLD_BACK,	X, 			X, 			1, 		X, 		CAP_P_RETURN},	
	{MNU_TYP_MOD_VALUE, NO, 		YES,		4,		X, 		CAP_P_PRN_DATA}, /* Miscellaneous */	
	{MNU_TYP_FLD_BACK,	X, 			X, 			1, 		X, 		CAP_P_RETURN}	

Within the menu handler routine, the lines

LCD.PrintArrayOfChar(vMnuItems[menuIndex].ptrCap, 1); /* Display menu ptrCap on first line */

LCD.PrintArrayOfChar(vMnuItems[vMnuItems[menuIndex].nextMenuIndex + counts].ptrCap, 2); /* Display menu caption */


LCD.PrintArrayOfChar(P(vMnuItems[menuIndex].ptrCap), 1); /* Display menu ptrCap on first line */

LCD.PrintArrayOfChar(P(vMnuItems[vMnuItems[menuIndex].nextMenuIndex + counts].ptrCap), 2); /* Display menu caption */

thanks to this little function:

char* P(const char* ptr) 
	strcpy_P(vCapBuffer, ptr);

In this way, you will be able to save hundreds of bytes from the SRAM which is good news to the Arduino’s developers.

Problem solving

/* No comments */