PlainDSP

plaindsp_audio_kit_s
The huge popularity of PlainDSP (merge of PlainFFT and PlainADC libraries) and the numerous requests for help drove me to think about a convenient solution for all designers, artists, students, professors, R&D people, prototypists who need to understand, experiment, create systems which feature advanced Digital Signal Processing on Arduino. The result of intense thoughts, design and writing is the collection PlainDSP kits, starting with the audio kit.

So please, pay a visit to plaindsp web site. By getting one of these kits you not only get a desirable product you also support a private initiative for popularizing science. Thank you.

 

Video of the Day

I was still a kid when JFK announced that he wanted an american to walk on the moon. At this time I was reading the adventures written by Jules VERNES and the moon was still this strange disc up in the night sky, intangible and mysterious.

Arrivee_Projectile_DTAL

“Arrivée Projectile DTAL ” by François Pannemaker, engraveur ; Henri de Montaut, drawer.

Although I had a weak idea about what was going on around the world, I was impressed by this young American President to whom nothing seemed impossible. Few years later, in the middle of a summer camp, the director called everybody and invited us to see the TV program on the small portable B&W receiver that he managed to get and plug on the battery of his car: Neil ARMSTRONG was walking on the moon! Some times later, Pink floyd then released “The dark Side of the Moon” and the Apollo program came to an end.

What was implicit to the strategists became more and more clear to the public: the lunar program led to the development of safety-critical systems and the practice of software engineering to program those systems. Much of this knowledge was issued from the Apollo program  and formed the basis of modern computing.

Next video brightly illustrates the boosting effect of the space programs on electronics. The author could have named it: “Form Gemini to Arduino” ! Enjoy

 

Poster of the Day

45ffe18e-b7b7-480a-bec6-1ee5fb6416ed-large

Although the situation looks critical, it looks like each of the passengers is finding a way to get out of the sinking boat. Everybody’s free to interpret this poster to his taste: Did the boat broke down due to the lack of communication and synergy? Is it an apology of “every man for himself”? Lost for lost, do these individual solutions match better the situation? Is it an advertisement for the DIY? Who knows?

An easy way to print multiple variables

The Serial.print() function is a nice way to print on the serial monitor but it is a bit frustrating to have to type something like :

Serial.print("Hello, I'm ");
Serial.print(myName);
Serial.print("and I'm ");
Serial.print(myAge);
Serial.println(" years old.");
Serial.print("I live in ");
Serial.print(myCountry);
Serial.print(", my hobbies are :")
Serial.print(myArduinoHobbies);
//...

It could be a good idea to useSerial.print() once, don’t you agree? C/C++ programming – on computers – provides one way to do so : using  the the  printf() function along with the stream operators of printf(). This function is available in C and C++, and it is called this way :

printf("Hello, I'm %s and I'm %d years old.\nI live in %s , my hobbies are : %s", myName, myAge, myCountry, myArduinoHobbies);

Any %s operator will be replaced by the given string and any %d operator will be replaced by the given integer in the order they are given. The ‘\n’ indicates that the cursor must go to a new line (a kind of short Serial.println()).

The stream operator “<<” is C++ specific and may be quite confusing when met for the first time but a simple example is self explainatory :

std::cout << "Hello, I'm " << myName << " and I'm " << myAge << " years old.\nI live in " << myCountry << " , my hobbies are : " << myArduinoHobbies;

std::cout is the terminal, the output of a program which runs on a computer.

Sadly, since these functions directly print to a monitor only available on a computer, it is not possible to use them on an Arduino boards. Some workarounds have been presented on the Arduino playground here and here and of course, Arduinoos provides its own ! It is not the ultimate one but it does the job. PlainPRINT allows you to use the printf() way and the streaming way, as follows :

_printer.Printf("Hello, I'm %s and I'm %d years old.\nI live in %s , my hobbies are : %s", myName, myAge, myCountry, myArduinoHobbies);

and :

_printer << "Hello, I'm " << myName << " and I'm " << myAge << " years old.\nI live in " << myCountry << " , my hobbies are : " << myArduinoHobbies;

The %letter specifiers of Printf() are not as numerous as the ones available from the original function printf(). Here are the different specifiers :

SPECIFIERINPUT TYPEOUTPUT FORMAT
uuint16_tdecimal
uluint32_tdecimal
dint16_tdecimal
lint32_tdecimal
ffloatdecimal
xuint16_thexadecimal
ouint16_toctal
buint16_tbinary
ccharASCII
schar*ASCII string
%char "%%" outputs "%"

Using Printf() has an advantage over using the stream operator: you can print an integer value in hexadecimal, octal or binary. Moreover, you can specify the precision of a floating point number, here is an example :

_printer.print("Pi with few decimals %4f", 3.14159); /* output : 3.1416 */

This code shortening library is, as usual, available on request.

Cry of the day

Cabu, the “grand Duduche” “father” has been murdered in Paris today with three cartoonists and seven other persons.

duduche

Tips and Tricks (Part 21)

Previous T&T

Convert numerical values in strings of characters.

Converting numerical values into strings of characters is easy as far as Serial functions is concerned . However you  may face one day or another the need for converting a numerical value for insertion within an existing string of characters (e.g. LCD, commands sent through SPI, etc.). Here is a collection of converting functions and their Serial equivalents. But firstly, we need to create a buffer which will contain the output from the conversion functions:

char *_vBuffer;

void setup(void)
{
	_vBuffer = (char*) malloc(16 * sizeof(char));
	Serial.begin(115200);
}

These few lines of code constitute the header and the setup section of the code. And here are the converting instructions:

/* Convert signed 32 bits integer */
ltoa(2863311530, _vBuffer, 10);
/* Results in -1431655766 */
Serial.println(_vBuffer);
/* Same as */
Serial.println(int32_t(2863311530));

/* Convert unsigned 32 bits integer */
ultoa(2863311530, _vBuffer, 10);
/* Results in 2863311530 */
Serial.println(_vBuffer);
/* Same as */
Serial.println(2863311530);

/* Convert 32 bits integer to hex */
itoa(2863311530, _vBuffer, 16);
/* Results in AAAAAAAA */
Serial.println(_vBuffer);
/* Same as */
Serial.println(2863311530, HEX);

/* Convert unsigned 16 bits integer */
utoa(43690, _vBuffer, 10);
/* Results in 43690 */
Serial.println(_vBuffer);
/* Same as */
Serial.println(43690);
/* Convert signed 16 bits integer */
itoa(43690, _vBuffer, 10);
/* Results in -21846 */
Serial.println(_vBuffer);
/* Same as */
Serial.println(int16_t(43690));	
/* Convert integer to hex */
itoa(43690, _vBuffer, 16);
/* Results in AAAA */
Serial.println(_vBuffer);
/* Same as */
Serial.println(43690, HEX);

/* Convert float using 6 decimals */
dtostrf(M_PI, 8, 6, _vBuffer);
Serial.println(_vBuffer);
/* Same as */
Serial.println(M_PI, 6);

More details about the converting function here

HTH

Arduino on French/German TV

Arduino on French (and German) TV, Arte channel: watch the Future program and enjoy!

Here are a few ideas that I picked up in the presentation:

  • Floriane: “It is fun when it works!”
  • David Cuartielles: Has fun discovering that the makers are ahead of his own imagination
  • It is good to see Arduino entering the conventional education system. However, the working conditions stay the same: two mates sitting at one table and facing the wall. Flip the chairs, tilt the screen and use large, open space tables!
  • Sailing boat driven by Arduino: awesome, however a little bit more expensive than 20€! The meta arduino components can be very expensive!
  • Bye bye Popy, see you at QuaiLab!

arte_arduino

News from the Plain DSP planet

You may like read this interesting paper dedicated to the use of the different types of memory available from an Arduino Board .

Next is a picture from a cousin microcontroller of the ATMEGA328, which illustrates the various areas dedicated to each main function of the microcontroller such as the memories.

atmel-ATmega8-8-bit-controller-die-shot

Credit: ZeptoBars

HTH

Stepper Motors (Part 4)

Part 12, 3, 4

Speed management

As seen in the previous posts,torques must be taken into account while setting the rotor speed during the acceleration, steady and deceleration phases. Starting from there, we have two options: the theoretical and the experimental approaches. Although playing with physics and maths might be fun, it is probably quicker and more efficient to go the experimental way.

Under loaded conditions, let’s firstly estimate the starting speed using at pretty low frequency  such as 50/100Hz. Then increase the frequency up to the point where the rotor can no longer cope with the driving wave. Now that we know the limits, all we have to do is to program a ramping process. The following sketch illustrates a simple routine which accelerates and decelerates the rotor speed automatically.

uint8_t _stepPinMask = (1 << PINB5);
uint8_t _dirPinMask = (1 << PINB4);
const uint16_t _pulsesPerRound = 48; /* As per motor specifications */
const uint16_t _pulseWMax = 15000;
const uint16_t _pulseWMin = 5000;
const uint16_t _pulseWSteps = 500;

void setup(void)
{ 
	/* Initialize ports */
	DDRB |= _stepPinMask;
	DDRB |= _dirPinMask;
}


void loop(void)
{
	Rotate(48 << 2, 1);
	Rotate(48 << 2, 0);
}


inline void Pulse(uint16_t pulseWidth) 
{
	PORTB |= _stepPinMask;
	delayMicroseconds(2);
	PORTB &=  ~_stepPinMask;
	if (pulseWidth < 16000) {
		delayMicroseconds(pulseWidth);
	} else {
		delay(pulseWidth / 1000);
	}
}


void Rotate(uint16_t steps, uint8_t direction) 
{
	/* Set direction */
	if (direction) {
		PORTB |= _dirPinMask;	
	} else {
		PORTB &= ~_dirPinMask;
	}
	uint16_t rampsSteps = ((_pulseWMax - _pulseWMin) / _pulseWSteps);
	/* Constrain the number of ramp steps to the whole number of steps */
	if (rampsSteps > steps) {
		rampsSteps = (steps >> 1);
	}
	/* Compute the number of steps at constant speed */
	uint16_t constSpeedSteps = (steps - (rampsSteps << 1));
	uint16_t pulseW = _pulseWMax;
	/* Acceleration phase */
	for (uint16_t i = 0; i < rampsSteps; i++) {
		Pulse(pulseW);
		pulseW -= _pulseWSteps; /* Decrease pulse width */
	}
	/* Constant speed phase */
	for (uint16_t i = 0; i < constSpeedSteps; i++) {
		Pulse(pulseW);
	}
	/* Deceleration phase */
	for (uint16_t i = 0; i < rampsSteps; i++) {
		Pulse(pulseW);
		pulseW += _pulseWSteps; /* Increase pulse width */
	}
}

Note that the pulsing engine has been taken apart in an online routine in order to ease the readability of the code. In the same manner, the maximum, minimum and step pulse width are set in global constants.

It is interesting to compare the effects of both the constant speed operation and the accelerated and decelerated operations on the torque applied to the motor while starting, stopping or changing directions. The instantaneous torque reduction might be very useful for reducing the instantaneous stress applied to the belt if such an accessory is attached to the motor via a timing belt pulley. The counterpart of this improvement is some noise at lower excitation frequencies.

[HOWTO] PlainDSP audio shield: M2M Communication system

The Critical Tinkers team recently achieved an amazing application based on the plaindsp kit. The M2M protocol they developed provides a smart way to send information to an Arduino board using a plaindsp audio shield from any sound emitting device (e.g. a cell phone). Next video is a teaser which demonstrates the principle of operation, as long as your computer is not muted !

Learn much more about this M2M communication application from plaindsp.com

Stepper Motors (Part 3)

Part 12, 3, 4

A4988 module

Let’s go into the details of this module through the understanding of its pinout:

pololu_3

The suggested basic wiring is as follows:

pololu_4

  • ~ENABLE: GND
  • MS1, 2 & 3: GND
  • ~RESET connected to ~SLEEP
  • STEP: step pulse
  • DIR: rotational direction
  • GND: same GND for VDD and VMOT
  • VDD: 3.3V to 5V
  • 1A,1B: winding 1
  • 2A, 2B: winding 2
  • VMOT: as per stepper motor specifications

Note: the ~ spanish tilde is used for negating a bit value in C ((~0 | 1) == 1); this sign is also used in Ki

Step pulses must simply comply with the required pulse width as per the A4988 datasheet.

pololu_5

The nice thing about this driver is that you do not have to care about the duty cycle of the step pulse signal. On the other hand, care shall be taken about choosing the appropriate frequency so that it fits the stepper motor requirements (Check the “Torque” paragraph in Part 1). There is no danger at all at using innapropriate frequency. If the frequency is too high, the rotor will erratically move or not move at all. If the frequency is too low, the rotor will move in rough steps and generate a growling sound.

Next is a code sample for running the A4988 module in a basic way:

uint8_t _stepPinMask = (1 << PINB5);
uint8_t _dirPinMask = (1 << PINB4);
uint16_t _pulsesPerRound = 48; /* As per the stepper motor specifications */

void setup(void)
{ 
	/* Initialize ports */
	DDRB |= _stepPinMask;
	DDRB |= _dirPinMask;
}


void loop(void)
{
	/* Rotate motor back and forth */
	Rotate(_pulsesPerRound << 1, 1, 5000);
	Rotate(_pulsesPerRound << 1, 0, 5000);
}


void Rotate(uint16_t steps, uint8_t direction, uint16_t pulseWidth) 
{
	if (direction) {
		PORTB |= _dirPinMask;	
	} else {
		PORTB &= ~_dirPinMask;
	}
	for (uint16_t i = 0; i < steps; i++) {
		/* Generate a step pulse. The pulse width is expressed in microseconds  
		The on state is twice the minimum requirement and it is insignificant 
		versus the off time which is mainly responsible for the frequency 
		setting */
		PORTB |= _stepPinMask;
		delayMicroseconds(2);
		PORTB &=  ~_stepPinMask;
		/* Use the most appropriate delay function */
		if (pulseWidth < 16000) {
			delayMicroseconds(pulseWidth);
		} else {
			delay(pulseWidth / 1000);
		}
	}
}

 

Next post on same subject