Ultrasonic scanner (Part 1)

Part 1

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.



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 */


Tips and Tricks (Part 27)

Previous T&T

This T&T deals with the compression of numerical data. Using the proposed algorithm, you will be able to compress a 16 bits unsigned integer (so as to say an uint16_t or an unsigned int data type). into an 8 bits unsigned integer (so as to say an uint8_t or an unsigned char data type). How come ?

Well, this algorithm takes advantage of the principle of operation of integer to float conversion. On completion of the compression algorithm, we get an 8 bits integer from which the 4 most significant bits (msb) contain the exponent and the 4 least significant bits (lsb) contain the mantissa. This arrangement has a drawback: the loss of precision. Next figure illustrates the errors which result from of a compression/decompression cycle:


These errors (up to 6%) are the price to pay for compressing data ranging from 0 to 65.535 down to a small compact integer ranging from 0 to 255 that uses only 2 bytes of memory…

Next diagram illustrates the way compression works


and this one illustrates the way decompression works


These diagrams are inspired by the Application Note AN498 from Silicon Labs, related to the Si114X light sensor.

Next is the code containing the compress and the decompress functions:

/* Compress an unsigned 16 bits integer into an unsigned 8 bits integer */
uint8_t Compress(uint16_t data)
	uint8_t res;
	if (data == 0) {
		res = 0x00;
	} else if (data == 1) {
		res = 0x0F;
	} else {
		uint8_t exponent = 15;
		while((data & 0x8000) != 0x8000){
			data <<= 1; /* Shift all bits one step to the left */
			exponent -= 1;
		uint8_t msb = exponent;
		/* Right align and mask the 4 fraction bits  */
		uint8_t lsb = ((data >> 11) & 0x0F);	
		/* Compute result */
		res = ((msb << 4) | lsb);
	/* Returned value */

/* Uncompress an unsigned 8 bits integer into an unsigned 16 bits integer */
uint16_t Uncompress(uint8_t data)
	/* Extract bits */
	uint8_t lsb = (data & 0x0F);
	uint8_t msb = ((data >> 4) & 0x0F);
	/* Compute value */
	float fraction = ((float)lsb / 16.0);
	if (msb != 0) {
		/* Applies to compressed 0s and 1s */
		fraction += 1.0;
	float exponent = (1UL << msb);
	uint16_t res = round(exponent * fraction);
	/* Returned value */

Note: Please check carefully the way the compressor manages the “0” and “1” values which have special behaviors in the domain of multiplication.

Enjoy !

Cool stuff of the day


Although very handy for basic applications, you may soon or later want to get rid of the basic timing functions from Arduino and start using advanced timing featuring better accuracy and avoid time consuming waiting loops.

There are several approaches to achieve this goal. Firstly, you may explore the web and try to find some information of interest. I you are lucky, you may find pages such as this one: Secrets of Arduino PWM or this one Les Timers. If you are patient and used to read advanced technical publications, you may just get a copy of the ATMEGA 328 microcontroller data sheet and read all about timers.

Alternatively, you may learn about timers by doing ! This on line code generator does that very well. All you need to do is to set the base frequency of your micro-controller (typically 16 MHz for UNO boards, 8 MHz for some low power boards) and the requested frequency. As a result of the calculations, the page displays the code necessary to drive any of the three timers from the ATMEGA 328.

Nota: Keep in mind that timer0 is used by Arduino for the timing functions such as millis() or micros().

And here is the link to this nice web site: Arduino Timer Interrupts Calculator


Tips and Tricks (Part 26)

Previous T&T

Building a tracking device is no big deal for the Arduino enthusiasts. All you need is an Arduino board (e.g. a UNO), a GPS shield and a GSM shield.


Too bad, we have a problem here because of the pin-out of the shields. The GSM shield uses pin 2 and 3 for the Rx and Tx connexions with the mode and pin 7 is used as the “Reset pin” which is responsible for remotely switching on and off the modem. Note that the “Power” button next to the SIM card does the same… manually.

On the other hand, the Adafruit “Data logger” shield features multiple functions such as an RTC, a SD card reader and a GPS chip. And this GPS shield uses pin 8 and 7 for Rx and Tx connexions. Blam ! Pin 7 is now overburdened.

Here is a simple turnaround which will allow you to plug both shields with very little modifications.



Remove the solder strap next to pin 7 and solder a wire between any other available pin (e.g. pin 6) and the live side of the conductive layer.


Get to the GSM library folder (typically: C:\Program Files (x86)\arduino\libraries\GSM\src) and apply two modes on files GSM3IO.h and GSM3ShieldV1.cpp. Both initially feature a line which looks like:

#define __RESETPIN__ 7

that you will change a comment like that

#define __RESETPIN__ 6 /* Reset pin changed from 7 to 6 by DL 20160809 */

Save both files and compile your code



Next Tip and Trick

analogRead alternative (Part2)

Part 1, 2

Starting from the presentation of the parametric version of an alternate analogRead function, here is a lean version of the whole code. The header section of the code

/* Sampling parameters */
uint32_t _interval = 200; /* Interval between two consecutive ADC reading cycles */
uint32_t _lastTime;

Next comes the ‘setup’ routine

void setup(void)
	/* Initialize the ADC */
	/* Console */
	/* Set the strating time */
	_lastTime = 0;

It contains the initialization parts of the ADC, console and timer. This section followed by the ‘loop’ routine

void loop(void)
	uint32_t _now = millis();
	/* Check elapsed time. This method handles millis overflow properly */
	if ((_now - _lastTime) >= _interval) {
		_lastTime = _now;  
		Serial.print(_now / 1000.0, 1);

Every time the millis() is equal or more than the interval time, the loop routine prints the time (in seconds) and the raw ADC counts. And here are the two ADC related functions for acquiring analog signals in the fastest possible mode. Keep in mind that under these conditions, the output of the AnalogRead function ranges from 0 to 256 (@ 5 V)

/* Initilalize analog read in fast mode and low resolution */
uint8_t InitADC(uint8_t channel)
	/* Reset register contents */
	ADCSRA = 0;
	ADCSRB = 0; 
	ADMUX = 0;
	/* Set voltage reference */
	ADMUX |= (1 << REFS0); /* DEFAULT VCC, 5 V */
	/* left align ADC value to 8 bits from ADCH register */
	ADMUX |= (1 << ADLAR);
	/* Set channel */ 
	ADMUX |= channel;
	/* Set pre-scaler */
	ADCSRA |= (1 << ADPS1);
	/* Enable ADC */
	ADCSRA |= (1 << ADEN);
	/* Start first conversion */
	ADCSRA |= (1 << ADSC); 
	/* Wait for conversion */
	while (ADCSRA & (1 << ADSC));

/* Simple analog to digital conversion */
uint16_t ADCRead(void)
	/* Start conversion */
	ADCSRA |= (1 << ADSC); 
	/* Wait for conversion */
	while (ADCSRA & (1 << ADSC));
	/* Returned ADC value */

Ultimately, if you really want to stick to the original analogRead format, here is the ‘advanced” ADCRead function:

/* Simple analog to digital conversion with analog channel parameter */
uint16_t ADCRead(uint8_t channel)
	/* Clear any lower 4 bits from the ADMUX register */
	ADMUX &= ~(0x0F)
	/* Set channel */
	ADMUX |= channel;
	/* Start conversion */
	ADCSRA |= (1 << ADSC); 
	/* Wait for conversion */
	while (ADCSRA & (1 << ADSC));
	/* Returned ADC value */


Amazing 3D printing

As a big fan of 3D printing, I had a lot of fun watching this video

In the next future, this is what we will hear from NASA records:

  • “Hello Houston, we have a problem”
  • “How can we help ?”
  • “Could you email us a cable clip so that we can tidy up this harness”
  • “Yep, you’ll get in within the next five minutes”
  • “In white please”