Saturday, December 29, 2012

New Year Projects

A quick teaser of some of the projects and components that will be featured on RC Arduino in the new year.

TFT Screen, 4 * Bi Color LED Matrix, Analogue Joystick, Microphone

Analogue Joystick, Touch Screen Overlay, Soft Pot.

A small collection of mini synths - Korg Monotron, Dubreq Stylophone, Bleep Labs Nebulophone.

RC Car Active Power Distribution
I am also planning to bring this monster back to life -
 Its two RC Cars joined together to make a twin motor 4wd car with independent throttle control to the front and rear axles. The result is a small car with way too much power, its very much in the spirit of a Group B rally car or the twin motored Suzuki Escudo rally car.

Stay Tuned

DUane B

Thursday, December 6, 2012

Arduino Basics: Google+ Page

I have just set up a Google+ page for the Arduino Basics blog posts.
If you haven't already tried it, Google+ is a great way to develop communities of like-minded individuals. It is a great way to share and ask questions. I held off from joining Google+, but now that I see it's advantages - I really like it. Anyway, I will still be blogging in the usual way, however, if you happen to be using Google+, please make sure to come and visit my page.

Click on the link below to have a look:
Arduino Basics Google+ Page.

Feel free to leave a comment if you wish.


Monday, December 3, 2012

Analog IR Temperature gauge


Introduction:
The IRTEMP module from Freetronics is an infrared remote temperature sensor that can be incorporated into your Arduino / microcontroller projects. It can scan a temperature between -33 to +220 C, and can be operated using a 3.3 to 5V power supply. It can be powered directly from the Arduino 5V pin.  This module can also provide an ambient temperature reading if required.
The Servo used in this project is a SG-5010 standard servo which will be utilised to display the temperature reading from the IRTEMP module.



Parts Required:
Freetronics Eleven or any compatible Arduino.
Freetronics IRTEMP module
MG-995  or SG-5010 Standard servo
Mini Breadboard 4.5cm x 3.5cm
Protoshieldand female header pins (not essential - but makes it more tidy)
9V Battery and Battery Clip
Wiresto connect it all together

Gauge parts:
Paper (to print the face of the gauge), and some glue to stick it to the wood.
MDF Standard panel (3mm width) - for the top and base of the gauge.
Galvanized bracket (25x25x40mm)
Timber screws: Hinge-long threads csk head Phillips drive (4G x 12mm)





The Video:



The Arduino Sketch:



     The above sketch was created using Fritzing.





Arduino Code:
You can download the Arduino IDE from this site.

The IRTemp gauge requires a driver library to be installed into the Arduino IDE.
The latest IRTemp driver library can be found here.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* -------------------------------------------------------
Analog IR Temperature Gauge: written by ScottC on 1st Dec 2012.
http://arduinobasics.blogspot.com/2012/12/arduino-basics-analog-ir-temperature.html


* Some of the code was adapted from a sketch by Andy Gelme (@geekscape)
* For more information on using the IRTEMP
see www.freetronics.com/irtemp

* IRTemp library uses an Arduino interrupt:
* If PIN_CLOCK = 2, then Arduino interrupt 0 is used
* If PIN_CLOCK = 3, then Arduino interrupt 1 is used
---------------------------------------------------------*/

#include "IRTemp.h"
#include <Servo.h>

Servo servo1;
static const byte PIN_DATA = 2;
static const byte PIN_CLOCK = 3; // Must be either pin 2 or pin 3
static const byte PIN_ACQUIRE = 4;

static const bool SCALE=false; // Celcius: false, Farenheit: true

/* Used to capture the temperature from the IRTEMP sensor */
float irTemperature;
int temp;

/* The minimum and maximum temperatures on the gauge. */
static const int minTemp = -45;
static const int maxTemp = 135;


/* The servo minimum and maximum angle rotation */
static const int minAngle = 0;
static const int maxAngle = 175;
int servoPos;

IRTemp irTemp(PIN_ACQUIRE, PIN_CLOCK, PIN_DATA);



/*----------------------SETUP----------------------*/

void setup(void) {

servo1.attach(9); // turn on servo
}


/*-----------------------LOOP-----------------------*/

void loop(void) {
irTemperature = irTemp.getIRTemperature(SCALE);
printTemperature("IR", irTemperature);

/* If you want the ambient temperature instead - then use the code below. */
//float ambientTemperature = irTemp.getAmbientTemperature(SCALE);
//printTemperature("Ambient", ambientTemperature);

}

/*-----------printTemperature function---------------*/

void printTemperature(char *type, float temperature) {

temp=(int) temperature;
servoPos = constrain(map(temp, minTemp,maxTemp,minAngle,maxAngle),minAngle,maxAngle);

if (isnan(temperature)) {
//is not a number, do nothing
}
else {

/* To test the minimum angle insert the code below */
//servoPos = minAngle;

/*To test the maximum angle, insert the code below */
//servoPos = maxAngle;

/* Rotate servo to the designated position */
servo1.write(servoPos);
}
}

The code above was formatted using hilite.me

Notes:
Ambient temperature: If you want to get the ambient temperature from the IRTEMP module, then have a look at lines 58-59.
Servo Angles: You will notice on line 36, the maximum servo angle used was 175. This value was obtained through trial and error (see below).

Calibrating the servo angles
You may need to calibrate your servo in order to move through an angle of 0 to 180 degrees without straining the motor.Change the minAngle on line 35to a safe value (for example: 10), and the maxAngle on line 36 to a value like 170. Remove the comment tag (//) on line 76, and then run the sketch. Lower the minAngle until it reaches the minimum value on the gauge, making sure that the servo doesn't sound like it is straining to keep it in position.

Add the comment tag (//) back in, and then take out the comment tag for line 79. And follow a similar process, until you reach the maximum value on the gauge. Once again, make sure that the servo is not making a straining noise to hold it at that value. Make sure to add the comment tag back in, when you have finished the calibration.

In this example, the servo's minAngle value was 0, and maxAngle value was 175 after calibration, however, as you can see from the video, the physical range of the servo turned out to be 0 to 180 degrees.




The Temperature Gauge Picture

The following gauge was created in Microsoft Excel using an X-Y chart.  Data labels were manually repositioned in order to get the desired numerical effect.









Saturday, December 1, 2012

Arduino Due DDS - Part 1 - Sinewaves and Fixed Point Maths

This post provides a quick introduction to Direct Digital Synthesis (DDS) on the Arduino Due. The sample sketch outputs a sinewave at a 44.1Khz sample rate with 12 bit resolution using the built in Digital To Analog Converter (DAC).

A related sketch which provides more interesting audio output without the explanation can be found here -
http://rcarduino.blogspot.com/2012/11/quick-and-dirty-synth-for-arduino-due.html

All of the Audio projects on RCArduino are based on this same DDS technique described below, see the following links for DDS Projects -
http://rcarduino.blogspot.com/2012/10/five-dollar-synthesiser.html
http://rcarduino.blogspot.com/2012/08/the-must-build-arduino-project-illutron.html

http://rcarduino.blogspot.com/2012/11/auduino-with-delay.html
http://rcarduino.blogspot.com/2012/08/adding-audio-to-arduino-projects.html
http://rcarduino.blogspot.com/2012/10/arduino-modular-synthesizer-part-one.html

Direct Digital Synthesis - Introduction
DDS is a common approach to generating sinewave output from digital systems. The approach is based around outputting samples from a description of the required waveform held in memory. The description is an array of samples which can be traversed to plot the waveform onscreen or by using DDS can generate a sinewave output at a selected frequency.

The 600 sample 12 Bit sine wave table used in the sketch below plotted on screen using processing -

The 128 sample 8 Bit wave tables used in the Illutron B synth -


Direct Digital Synthesis - Sample Rate
To generate an output waveform we need a way to regularly update the output value, we do this by using a timer interrupt. The frequency of this interrupt is termed the sample rate, in our case we are using a 44.1Khz sample rate meaning that we have an interrupt triggering 44,100 times per second.

As this interrupt is triggering at such a high rate it is very important that we keep it efficient, this is the reason for using a pre computed wavetable rather than computing the sine samples on the fly.

Direct Digital Synthesis - Frequency Generation
We can generate different frequencies by changing the rate at which we traverse through the wave table. One pass through the wavetable provides one complete cycle of the selected waveform (sine in our case). If we pass through the table once in 44,100 interrupts we generate a frequency of 1Hz, if we pass through 100 times faster, we get a sinewave output at a frequency of 100Hz.

Direct Digital Synthesis - Implementation and Terminology
The following terms are commonly used in reference to DDS and variations are used throughout the RC Arduino audio projects.

1) Phase Accumulator - this is an array index which points to the current sample in the selected wavetable.
2) Phase Increment - this value is used to advance the Phase Accumulator each time the interrupt is called.

Example usage of the phase accumulator used inside the timer interrupt to select the next sample in the wave table array -

// Update the phase accumulator by adding the phase increment
ulPhaseAccumulator += ulPhaseIncrement;

// get the current sample from the sine table using the phase accumulator as the index  
uint32_t ulOutput = nSineTable[ulPhaseAccumulator>>20];

Direct Digital Synthesis - Fixed Point Maths
To generate a full range of frequencies we will often need to use fractional values for our phase accumulator.


The usual method of working with fractional values is to use the float data type however in DDS we need our interrupts to run as fast as possible. With very few exceptions microcontrollers are not able to process the float data type at high speed, the solution is to use fixed point integer maths. 

Fixed Points For Higher Integer Precision
There are many applications of fixed point arithmetic but in DDS the main use is to provide increased precision - equivalent to having many decimal points while still using the high speed integer (whole number) data type.

To get extra precision we use more bits than we need to represent our data range. For example the sample code below has a wave table size of 600 samples so the range of we need for our phase accumulator is 0 to 599.

We can represent this range with 10 bits but if we use 16 bits we have 6 additional bits of precession.


16 Bit Integer














Bit  15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Value 32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1

















Fixed Point 10.6 using 16 Bit Integer












Bit  15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Value 1024 512 256 128 64 32 16 8 4 2 1 0.5 0.25 0.125 0.0625 0.0313

We use this additional precision to perform fractional addition to the phase accumulator, the 10.6 format gives 1/32 precision as the least significant bit.

Fixed point addition - we know its fixed point, the compiler doesn't

// Update the phase accumulator by adding the phase increment
ulPhaseAccumulator += ulPhaseIncrement;  

This line of code is actually adding two fixed point numbers, part of the trick is that the compiler does not know this, it sees them simply as two integers which it processes using very fast hardware integer addition.

When we want to use the phase accumulator as the array index, we perform an arithmetic shift six places to the right, this drops off the six bits of additional precession and leaves us with a 10 bit integer value for the array index.

// drop the six bits of additional precision and access the remaining 10 bits as an integer array index in the range 0 - 599

uint16_t unOutputValue = sineTable[ulPhaseAccumulator>>6];

The only trick to fixed point maths is to figure out a scheme which will work for your project and stick to it. Remember the compiler does not know that you are treating part of the number as fractions so the responsibility is on you the programmer to keep consistency.

Fixed Point In The RCArduino DDS Example Sketch
The standard data type for the 32 bit Arduino Due is a 32 bit integer, this gives us scope for very high levels of precession in integer maths. The scheme used for the phase increment and phase accumulator variables in the sample sketch is 12.20 (12+20 = 32 Bits) this can be seen in the following line of code where the precision is shifted out to access the pure 12 bit integer value -

uint32_t ulOutput = nSineTable[ulPhaseAccumulator>>20];

Where ever you see code that makes extensive use of '>>' operations you might be looking at fixed point arithmetic, in a follow up post we will look at how we perform fast fixed point multiplication. This is another key to fast and flexible synthesizer engines.

Fixed Point Multiplication is used in Audio synthesis to apply envelopes and amplitude modulation.

Envelope Applied to a DDS sine wave using Fixed Point Maths in the Illutron B Project -

DDS Sinewave for Arduino Due - The Sketch
Use a potentiometer connected to analog pin 0 to control the pitch. To hear the output you can use an amplifier circuit such as this one used throughout RCArduino - 

http://rcarduino.blogspot.com/2012/08/adding-audio-to-arduino-projects.html

The sinewave is output through DAC0 - Note that the DAC does not provide a full 0-3.3volt swing, this is a hardware limitation of the SAM3X8E chip.


Caution : The SAM3X8E microcontroller at the heart of the Arduino Due is less able to sink and source current than the AVR family of chips used in the 8-Bit Arduinos. See the update below for the most recent recommendations - 

Update 09/06/2013 - Gaétan Ro has taken things much further in the latest build of his Groovuino project. The Project uses the technique described here combined with some sensors, a sequencer and filter to produce a really nice sounding groovebox. I plan to build one of these for myself and hope to be able to help Gaétan with its further development.

http://www.youtube.com/watch?v=EqI2hEVbMPI

Gaéta's blog -  http://groovuino.blogspot.com/

Update 28/03/2013 : There is little information on the SAM3X8E DAC in the datasheet however Arduino forum used 'stimmer' has found recommendations on a closely related chip which suggest that a 2K Ohm resistor should be placed as a series current limiting resistor between the DAC Output and the load. This assumes that the load has no resistance of its own which will be the case if you accidentally short something, if you know the resistance of your load, you can reduce this value, if not, its a reasonable starting point and will protect against accidents. For more information see the original thread here - http://arduino.cc/forum/index.php/topic,139733.15.html

Update 28/03/2013 : Gaétan Ro has been building on the techniques here to produce an Arduino Due based groove box he is calling the 'Groovuino'. You can hear a clip of the project in action here -

https://soundcloud.com/gaetino/groovuino

And follow the future development on the blog Gaétan has started here -

http://groovuino.blogspot.ae/

// RCArduino DDS Sinewave for Arduino Due
// RCArduino DDS Sinewave by RCArduino is licensed under a Creative Commons Attribution 3.0 Unported License.
// Based on a work at rcarduino.blogspot.com.

// For helpful background information on Arduino Due Timer Configuration, refer to the following link
// thanks to Sebastian Vik
// http://arduino.cc/forum/index.php?action=post;topic=130423.15;num_replies=20

// For background information on the DDS Technique see
// http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/

// For audio sketches making extensive use of DDS Techniques, search the RCArduino Blog
// for the tags Audio or synth

// These are the clock frequencies available to the timers /2,/8,/32,/128
// 84Mhz/2 = 42.000 MHz
// 84Mhz/8 = 10.500 MHz
// 84Mhz/32 = 2.625 MHz
// 84Mhz/128 = 656.250 KHz
//
// 44.1Khz = CD Sample Rate
// Lets aim for as close to the CD Sample Rate as we can get -
//
// 42Mhz/44.1Khz = 952.38
// 10.5Mhz/44.1Khz = 238.09 // best fit divide by 8 = TIMER_CLOCK2 and 238 ticks per sample
// 2.625Hmz/44.1Khz = 59.5
// 656Khz/44.1Khz = 14.88

// 84Mhz/44.1Khz = 1904 instructions per tick

// the phase accumulator points to the current sample in our wavetable
uint32_t ulPhaseAccumulator = 0;
// the phase increment controls the rate at which we move through the wave table
// higher values = higher frequencies
volatile uint32_t ulPhaseIncrement = 0;   // 32 bit phase increment, see below

// full waveform = 0 to SAMPLES_PER_CYCLE
// Phase Increment for 1 Hz =(SAMPLES_PER_CYCLE_FIXEDPOINT/SAMPLE_RATE) = 1Hz
// Phase Increment for frequency F = (SAMPLES_PER_CYCLE/SAMPLE_RATE)*F
#define SAMPLE_RATE 44100.0
#define SAMPLES_PER_CYCLE 600
#define SAMPLES_PER_CYCLE_FIXEDPOINT (SAMPLES_PER_CYCLE<<20)
#define TICKS_PER_CYCLE (float)((float)SAMPLES_PER_CYCLE_FIXEDPOINT/(float)SAMPLE_RATE)

// to represent 600 we need 10 bits
// Our fixed point format will be 10P22 = 32 bits


// We have 521K flash and 96K ram to play with

// Create a table to hold the phase increments we need to generate midi note frequencies at our 44.1Khz sample rate
#define MIDI_NOTES 128
uint32_t nMidiPhaseIncrement[MIDI_NOTES];

// fill the note table with the phase increment values we require to generate the note
void createNoteTable(float fSampleRate)
{
  for(uint32_t unMidiNote = 0;unMidiNote < MIDI_NOTES;unMidiNote++)
  {
    // Correct calculation for frequency
    Serial.print(unMidiNote);
    Serial.print(" ");
    float fFrequency = ((pow(2.0,(unMidiNote-69.0)/12.0)) * 440.0);
    Serial.print(fFrequency);
    Serial.print(" ");
   
    nMidiPhaseIncrement[unMidiNote] = fFrequency*TICKS_PER_CYCLE;
    Serial.println(nMidiPhaseIncrement[unMidiNote]);
  }
}

// Create a table to hold pre computed sinewave, the table has a resolution of 600 samples
#define WAVE_SAMPLES 600
// default int is 32 bit, in most cases its best to use uint32_t but for large arrays its better to use smaller
// data types if possible, here we are storing 12 bit samples in 16 bit ints
uint16_t nSineTable[WAVE_SAMPLES];

// create the individual samples for our sinewave table
void createSineTable()
{
  for(uint32_t nIndex = 0;nIndex < WAVE_SAMPLES;nIndex++)
  {
    // normalised to 12 bit range 0-4095
    nSineTable[nIndex] = (uint16_t)  (((1+sin(((2.0*PI)/WAVE_SAMPLES)*nIndex))*4095.0)/2);
    Serial.println(nSineTable[nIndex]);
  }
}

void setup()
{
  Serial.begin(9600);

  createNoteTable(SAMPLE_RATE);
  createSineTable();
 
  /* turn on the timer clock in the power management controller */
  pmc_set_writeprotect(false);
  pmc_enable_periph_clk(ID_TC4);

  /* we want wavesel 01 with RC */
  TC_Configure(/* clock */TC1,/* channel */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);
  TC_SetRC(TC1, 1, 238); // sets <> 44.1 Khz interrupt rate
  TC_Start(TC1, 1);
 
  // enable timer interrupts on the timer
  TC1->TC_CHANNEL[1].TC_IER=TC_IER_CPCS;
  TC1->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS;
 
  /* Enable the interrupt in the nested vector interrupt controller */
  /* TC4_IRQn where 4 is the timer number * timer channels (3) + the channel number (=(1*3)+1) for timer1 channel1 */
  NVIC_EnableIRQ(TC4_IRQn);

  // this is a cheat - enable the DAC
  analogWrite(DAC0,0);
}

void loop()
{
  // read analog input 0 drop the range from 0-1024 to 0-127 with a right shift 3 places,
  // then look up the phaseIncrement required to generate the note in our nMidiPhaseIncrement table
  uint32_t ulInput = analogRead(0);
  ulPhaseIncrement = nMidiPhaseIncrement[ulInput>>3];
}

void TC4_Handler()
{
  // We need to get the status to clear it and allow the interrupt to fire again
  TC_GetStatus(TC1, 1);
 
  ulPhaseAccumulator += ulPhaseIncrement;   // 32 bit phase increment, see below

  // if the phase accumulator over flows - we have been through one cycle at the current pitch,
  // now we need to reset the grains ready for our next cycle
  if(ulPhaseAccumulator > SAMPLES_PER_CYCLE_FIXEDPOINT)
  {
   // DB 02/Jan/2012 - carry the remainder of the phase accumulator
   ulPhaseAccumulator -= SAMPLES_PER_CYCLE_FIXEDPOINT;
   }

  // get the current sample  
  uint32_t ulOutput = nSineTable[ulPhaseAccumulator>>20];
 
  // we cheated and user analogWrite to enable the dac, but here we want to be fast so
  // write directly 
  dacc_write_conversion_data(DACC_INTERFACE, ulOutput);
}