Monday, May 30, 2011

Tutorial: Video output from your Arduino

This is chapter thirty-five of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A seemingly endless series of tutorials about the Arduino universe. The first chapter is here, the complete series is detailed here. Any files from tutorials will be found here.

Welcome back fellow arduidans!

In this chapter we will examine something different – the ability of our Arduino and compatible boards to create composite video output. In other words, displaying stuff from the Arduino on a TV. A lot of people were unaware of the ability to do this, however the process is very simple and not difficult to implement from a hardware perspective. Within this chapter we will learn to construct the minumum hardware required and demonstrate basic functions to get started.

To whet your appetite, here is a quick video demonstration of what is possible:

You can’t expect too much from a 16 Mhz microcontroller without a video card… but the price is right, and with some imagination and the right functions you can do quite well. To make this happen we need to knock out some hardware of our own (or you could buy a kitinstead). Connection is very easy. First we need to locate three pins on our Arduino board. They will be used to output Sync, Video and also GND. For those with Arduno Uno/Duemilanove/Freetronics Eleven etc Sync is digital 9, video is digital 7 and GND is … GND. If you have a Mega/Mega2560 Sync is digital 11 and video is D29. There is also the ability to generate audio with the methods in this article, and if you want to do this the Uno (etc.) pin is digital 11 or 10 on the Mega.

The monitor or television used needs to have a composite video-in socket (jack). For those with older televisions that have a VCR connected, you could use the video-in socket on the VCR.

The schematic for video out is very simple, you only need two normal 0.25W resistors and a video lead:

(tronixCAD v1.0…)

If you’re not up for soldering into an RCA plug, a simple way is to chop up a standard video lead as such:

Then just wire the termination of the two resistors to the centre core (“pin”) and GND to the shield. For the purpose of this article I have made a quick TV-out shield that also includes a thumb joystick (as reviewed here).

A real triumph of engineering… however it solves the problem. The vertical trimmer is connected to A0;  the horizontal to A1; the button to digital 8 via a 10k0 pull-up resistor. Next, you will need to download and install the arduino-tvout library. It can be found here. We will use the TVoutBeta1.zip version. Copy the downloaded folder into the ../arduino-002x/libraries folder and restart the Arduino IDE. Those of you who may have a nootropic design Hackvision – please note your library is different.

Now to see how to integrate TV-out into our sketch. We will run through the basic functions which integrated with your imagination should see some interesting results…  So let’s go!

For every project, place these two lines at the top of your sketch:

#include <TVout.h>  TVout TV;

The first brings in the library, and the second line creates an instance of TV to use with the library functions. Next, we need to activate TVout and select the appropriate broadcast standard (PAL or NTSC). In void setup() use either

TV.start_render(_NTSC) // for NTSC (or)
TV.start_render(_PAL); // for PAL system

Now for the main functions. The first one of interest will be:

TV.clear_screen();

which … clears the screen. Or if you would like to fill the screen with white, use

TV.fill_screen(1);

Moving on – to write some text. First we need to select a font. There are three basic fonts to choose from:

  • font4x6 (each character being 4 pixels by 6 pixels, etc.)
  • font6x8
  • font8x8

Well there is four, but it wouldn’t display for me. Working on it! To choose a font use:

TV.select_font(font4x6); // using font4x6

Then to write the text, choose the screen location with:

TV.set_cursor(x,y);

then display the text with:

TV.print("Hello, world..."); // etc

You can also use TV.println(); to add a carriage return as expected. Display single characters with a position in the one function using:

TV.print_char(x,y,c); // c is the character to display

So let’s have a look at the various fonts in action with the following sketch (download):

Example 35.1

/* Example 35.1 - arduino-tvout text demonstration http://tronixstuff.wordpress.com/tutorials > chapter 35 | CC by-sa-nc */  #include #include TVout TV;  int d=10; // for delay purposes char c='X';  void setup() { TV.begin(_PAL); // for PAL system TV.clear_screen(); }  void loop() { TV.select_font(font4x6); for (int a=0; a<6; a++) { for (int b=0; b<128; b++) { TV.print_char(b,a*6,c); delay(d); TV.clear_screen(); } } delay(1000); TV.clear_screen();    TV.select_font(font6x8); for (int a=0; a<6; a++) { for (int b=0; b<128; b++) { TV.print_char(b,a*8,c); delay(d); TV.clear_screen(); } } delay(1000); TV.clear_screen();    TV.select_font(font8x8); for (int a=0; a<6; a++) { for (int b=0; b<128; b++) { TV.print_char(b,a*8,c); delay(d); TV.clear_screen(); } } delay(1000); TV.clear_screen(); }

Now to move into the 1970s with some basic graphical functions. We have a screen resolution of 128 by 96 pixels to work with. When planning your display, you need to ensure that the sketch never attempts to display a pixel outside of the 128 x 96 screen area. Doing so generally causes the Arduino to reboot.

Question – When did colour TV broadcasting start in Australia?

First let’s start with basic pixels. To draw a pixel, use:

TV.set_pixel(x,y,z);

where x and y are the coordinates of the pixel, and z is the colour (1 = white, 0 = black, 2 = inverse of current pixel’s colour). You want more than a pixel? How about a line:

TV.draw_line(x1,y1,x2,y2,colour);

Draws a line from x1, y1 to x2, y2 of colour colour. (1 = white, 0 = black, 2 = inverse of current pixel’s colour).

Rectangles? Easy:

TV.draw_rectangle(x,y,w,h,colour,fill);

Draws a rectangle with the top-left corner at x,y; width w, height h, colour and optional fill colour.

Circles are just as simple:

TV.draw_circle(x,y,r,colour,fill);

Draws a circle with centre at x,y; radius r pixels, edge colour, optional fill colour.

Now to see these functions in action with the following sketch (download):

Example 35.2

/* Example 35.2 - arduino-tvout font demonstration II http://tronixstuff.wordpress.com/tutorials > chapter 35 | CC by-sa-nc */  #include TVout TV;  int d=100; // for delay purposes int x1,x2,y1,y2,r=0;   void setup() { TV.begin(_PAL); // for PAL system TV.clear_screen(); randomSeed(analogRead(0)); // seed the random number generator }  void pixels() { TV.clear_screen(); for (int a=0; a<200; a++) { x1=random(128); y1=random(96); TV.set_pixel(x1,y1,2); delay(d); } delay(1000); TV.clear_screen(); }  void lines() { TV.clear_screen(); for (int a=0; a<96; a++) { TV.draw_line(0,a,127,a,1); delay(d); } delay(500); for (int a=0; a<96; a++) { TV.draw_line(0,a,127,a,0); delay(d); } TV.clear_screen(); delay(500); }    void circles() { TV.clear_screen(); for (int i=0; i<30; i++) { TV.draw_circle(64,48,i,1,0); delay(200); TV.draw_circle(64,48,i,1,1); delay(200); TV.draw_circle(64,48,i,0,0); delay(200); } delay(1000); TV.clear_screen(); }    void loop() { pixels(); lines(); circles(); }

And for the video demonstration:

So there you have it, a start with Arduino and TV-out. Sorry about the short post but unpaid time is rare at the moment. In the near future we will continue with displaying bitmap images and gaming. To keep up with new articles, stay tuned for upcoming Arduino tutorials by subscribing to the blog, RSS feed (top-right), twitter or joining our Google Group. Furthermore, a big thanks tohttp://code.google.com/u/mdmetzle/ for the arduino-tvout library

If you have any questions about the processes or details in this article, please ask in our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, there is the odd competition or give-away –  and we can all learn something.

Otherwise, have fun, stay safe, be good to each other – and make something!

Tuesday, May 24, 2011

Kit review – nootropic design Digit Shield

Hello readers

Time once again to examine another kit. This week we have the nootropic design Digit Shield for Arduino Uno/Duemilanove andcompatible boards. Although a finger can be called a digit this shield is not some sort of biotechnological experiment – instead it gives us four seven-segment LED displays to show various forms of numerical data from our Arduino sketches.

Although many people may be tempted to use a standard LCD unit, there are a few advantages to using an LED display – such as digit size, enhanced readability in daylight, and LED displays are generally much more robust than LCDs. Therefore there should be many uses for the Digit Shield. Furthermore, the people at nootropic design have been awesome as they support theOpen Hardware Definition 1.0, and the Digit Shield design files have been made available under Creative Commons attribution-share alike.

First let’s run through construction, then operation with some demonstrations. The kit arrives in a nice reusable bag with a pointer to the online instructions:

Kit construction was relatively simple thanks to the excellent instructions by nootropic design. All the parts required for completion are included, except for IC sockets:

My demonstration kit included green LED displays, however it is also available in red-orange, depending on the retail outlet you choose. Once again the PCB is well laid out, with a good solder mask and a nicely labelled silk screen on top:

Question - Name the creator of the fictional computer “Colossus”

Now to start soldering. The process is nothing out of the ordinary, and should take around half an hour at the most. First in are the resistors:

Notice how the current-limiting resistors for the LED segments will be under the LED displays. So now we solder in the LED modules and create a resistor jail:

Now for the shift register and BCD to decimal ICs. I found inserting them a little tricky due to my large hands and the LED display already being in place, so it would be easier to fit the ICs before the LED modules:

This leaves us with the transistors, capacitors, header sockets and the reset button:

After soldering the reset button, you may need trim down the solder and legs (as shown below) otherwise there is a possibility they will rub the DC input socket on the Arduino board:

Finally the shield pins are fitted and the shield is ready:

The next task is to download and install the Digit Shield’s Arduino library. The latest version can be found here. Extract the folder into your

../arduino-002x/libraries

folder, then restart the Arduino IDE software.  A quick test of the shield can be accomplished with the SimpleCounter sketch available from the inbuilt examples. To find this, select File>Examples>DigitShield>SimpleCounter in the Arduino IDE, and upload the sketch. Hold onto the desk as you watch some numbers increment:


Using the shield in your own sketch is quite simple. Instead of reinventing the wheel there is an excellent explanation of the various functions available on the lower section of this page. A very useful feature is when the shield cannot display a number – it shows all four decimal points instead. The only slight criticism that comes to mind is the inability to directly display hexadecimal digits A~F, as the LED units lend themselves nicely to doing so; or the option of controlling each LED segment individually with a simple function. So let’s see if that is possible…

One of the joys of open hardware is the fact we can get the schematic, see how it works and attempt to solve such dilemmas ourselves. For those without software that can read Cadsoft EAGLE files, here is the schematic in .pdf format. The section we need to see is how the LED segments are driven. Look for the 74HC595 and 74LS247 ICs. Serial data is shifted out from the Arduino digital pins to the 74HC595 shift register. (For more information about how 74HC595s work with Arduino please visit this tutorial).

Outputs A~D (Q0~Q3) represent binary-coded decimal output and the outputs E~H (Q4~Q7) control the transistors which select the current digit to use. The BCD output is fed to the 74LS247 BCD to seven-segment drive IC. Although this is a very useful IC, it can only display the decimal digits and a few odd characters (see page two of the data sheet.pdf). So this leaves us unable to modify our sketches or the shield library to solve our problem. Such is life!

Perhaps the people at nootropic design can consider a change in the hardware for the next version to incorporate such requirements. However there are several projects available in the Digit Shield’s website that may be of interest, including a way to daisy-chain more than one shield at a time.

Nevertheless the Digit Shield is a simple kit that makes displaying Arduino-generated numerical data simple and clear. Furthermore lovers of blinking LEDs will have a ball. For further questions about the Digit Shield contact nootropic design or perhaps post on their forum.  The Digit Shield is available from Little Bird Electronics.

As always, thank you for reading and I look forward to your comments and so on. Furthermore, don’t be shy in pointing out errors or places that could use improvement. Please subscribe using one of the methods at the top-right of this web page to receive updates on new posts, follow me on twitter or facebook, or join our Google Group for further discussion.

High resolution images are available on flickr.

[Note - The kit was purchased by myself personally and reviewed without notifying the manufacturer or retailer]

Otherwise, have fun, be good to each other – and make something! 

Monday, May 16, 2011

Tutorial: Arduino and the SPI bus

This is chapter thirty-four of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A seemingly endless tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here. Any files from tutorials will be found here.

Welcome back fellow arduidans!

This is the first of several forthcoming chapters in which we are going to start investigating the SPI data bus, and how we can control devices using it with our Arduino systems. The SPI bus may seem to be a complex interface to master, however with some brief study of this explanation and practical examples you will soon become a bus master! To do this we will learn the necessary theory, and then apply it by controlling a variety of devices. In this tutorial things will be kept as simple as possible.

But first of all, what is it? And some theory…

SPI is an acronym for “Serial Peripheral Interface”. It is a synchronous serial data bus – data can travel in both directions at the same time, as opposed to (for example) the I2C bus that cannot do so. To allow synchronous data transmission, the SPI bus uses four wires. They are called:

  • MOSI – Master-out, Slave-in. This line carries data from our Arduino to the SPI-controlled device(s);
  • MISO – Master-in, Slave out. This line carries data from the SPI-controlled device(s) back to the Arduino;
  • SS – Slave-select. This line tells the device on the bus we wish to communicate with it. Each SPI device needs a unique SS line back to the Arduino;
  • SCK – Serial clock.

Within these tutorials we consider the Arduino board to be the master and the SPI devices to be slaves. On our Arduino Duemilanove/Uno andcompatible boards the pins used are:

  • SS – digital 10. You can use other digital pins, but 10 is generally the default as it is next to the other SPI pins;
  • MOSI – digital 11;
  • MISO – digital 12;
  • SCK – digital 13;

Arduino Mega users – MISO is 50, MOSI is 51, SCK is 52 and SS is usually 53. You can control one or more devices with the SPI bus. For example, for one device the wiring would be:

Data travels back and forth along the MOSI and MISO lines between our Arduino and the SPI device. This can only happen when the SS line is set to LOW. In other words, to communicate with a particular SPI device on the bus, we set the SS line to that device to LOW, then communicate with it, then set the line back to HIGH. If we have two or more SPI devices on the bus, the wiring would resemble the following:


Notice how there are two SS lines – we need one for each SPI device on the bus. You can use any free digital output pin on your Arduino as an SS line. Just remember to have all SS lines high except for the line connected to the SPI device you wish to use at the time.

Data is sent to the SPI device in byte form. You should know by now that eight bits make one byte, therefore representing a binary number with a value of between zero and 255. When communicating with our SPI devices, we need to know which way the device deals with the data – MSB or LSB first. MSB (most significant bit) is the left-hand side of the binary number, and LSB (least significant bit) is the right-hand side of the number. That is:

Apart from sending numerical values along the SPI bus, binary numbers can also represent commands. You can represent eight on/off settings using one byte of data, so a device’s parameters can be set by sending a byte of data. These parameters will vary with each device and should be illustrated in the particular device’s data sheet. For example, a digital potentiometer IC with six pots:

This device requires two bytes of data. The ADDR byte tells the device which of six potentiometers to control (numbered 0 to 5), and the DATA byte is the value for the potentiometer (0~255). We can use integers to represent these two values. For example, to set potentiometer number two to 125, we would send 2 then 125 to the device.

How do we send data to SPI devices in our sketches?

First of all, we need to use the SPI library. It is included with the default Arduino IDE installation, so put the following at the start of your sketch:

#include "SPI.h"

Next, in void.setup() declare which pin(s) will be used for SS and set them as OUTPUT. For example,

    pinMode(ss, OUTPUT);

where ss has previously been declared as an integer of value ten. Now, to activate the SPI bus:

SPI.begin();

and finally we need to tell the sketch which way to send data, MSB or LSB first by using

SPI.setBitOrder(MSBFIRST);

or

 SPI.setBitOrder(LSBFIRST);

When it is time to send data down the SPI bus to our device, three things need to happen. First, set the digital pin with SS to low:

digitalWrite(SS, LOW);

Then send the data in bytes, one byte at a time using:

SPI.transfer(value);

Value can be an integer/byte between zero and 255. Finally, when finished sending data to your device, end the transmission by setting SS high:

digitalWrite(ss, HIGH);

Sending data is quite simple. Generally the most difficult part for people is interpreting the device data sheet to understand how commands and data need to be structured for transmission. But with some practice, these small hurdles can be overcome.

Now for some practical examples!

Time to get on the SPI bus and control some devices. By following the examples below, you should gain a practical understanding of how the SPI bus and devices can be used with our Arduino boards.

Example 34.1

Our first example will use a simple yet interesting part – a digital potentiometer (we also used one in the I2C tutorial). This time we have a Microchip MCP4162-series 10k rheostat:


Here is the data sheet.pdf for your perusal. To control it we need to send two bytes of data – the first byte is the control byte, and thankfully for this example it is always zero (as the address for the wiper value is 00h [see table 4-1 of the data sheet]).  The second byte is the the value to set the wiper, which controls the resistance. So to set the wiper we need to do three things in our sketch…

First, set the SS (slave select) line to low:

digitalWrite(10, LOW);

Then send the two byes of data:

SPI.transfer(0); // command byte
SPI.transfer(value); // wiper value

Finally set the SS line back to high:

digitalWrite(10, HIGH);

Easily done. Connection to our Arduino board is very simple – consider the MCP4162 pinout:

Vdd connects to 5V, Vss to GND, CS to digital 10, SCK to digital 13, SDI to digital 11 and SDO to digital 12. Now let’s run through the available values of the MCP4162 in the following sketch (download):

/* Example 34.1 - SPI bus demo using a Microchip MCP4162 digital potentiometer [http://bit.ly/iwDmnd] http://tronixstuff.com/tutorials > chapter 34 | CC by-sa-nc | John Boxall */  #include "SPI.h" // necessary library int ss=10; // using digital pin 10 for SPI slave select int del=200; // used for various delays  void setup() { pinMode(ss, OUTPUT); // we use this for SS pin SPI.begin(); // wake up the SPI bus. SPI.setBitOrder(MSBFIRST); // our MCP4162 requires data to be sent MSB (most significant byte) first }  void setValue(int value) { digitalWrite(ss, LOW); SPI.transfer(0); // send command byte SPI.transfer(value); // send value (0~255) digitalWrite(ss, HIGH); }  void loop() { for (int a=0; a<256; a++) { setValue(a); delay(del); } for (int a=255; a>=0; --a) { setValue(a); delay(del); } }

Now to see the results of the sketch. In the following video clip, a we run up through the resistance range and measure the rheostat value with a multimeter:


Before moving forward, if digital potentiometers are new for you, consider reading this short guide written by Microchip about the differences between mechanical and digital potentiometers.

Example 34.2

In this example, we will use the Analog Devices AD5204 four-channel digital potentiometer (data sheet.pdf). It contains four 10k ohm linear potentiometers, and each potentiometer is adjustable to one of 256 positions. The settings are volatile, which means they are not remembered when the power is turned off. Therefore when power is applied the potentiometers are all pre set to the middle of the scale. Our example is the SOIC-24 surface mount example, however it is also manufactured in DIP format as well.

To make life easier it can be soldered onto a SOIC breakout board which converts it to a through-hole package:

In this example, we will control the brightness of four LEDs. Wiring is very simple. Pinouts are in the data sheet.pdf.


And the sketch (download):

/* Example 34.2 - SPI bus demo using Analog Devices AD5204 digital potentiometer [http://bit.ly/joB51b] http://tronixstuff.com/tutorials > chapter 34 | CC by-sa-nc | John Boxall */  #include "SPI.h" // necessary library int ss=10; // using digital pin 10 for SPI slave select int del=5; // used for fading delay  void setup() { pinMode(ss, OUTPUT); // we use this for SS pin SPI.begin(); // wake up the SPI bus. SPI.setBitOrder(MSBFIRST); // our AD5204 requires data to be sent MSB (most significant byte) first. See data sheet page 5 allOff(); // we do this as pot memories are volatile }  void allOff() // sets all potentiometers to minimum value { for (int z=0; z<4; z++) { setPot(z,0); } }  void allOn() // sets all potentiometers to maximum value { for (int z=0; z<4; z++) { setPot(z,255); } }  void setPot(int pot, int level) // sets potentiometer 'pot' to level 'level' { digitalWrite(ss, LOW); SPI.transfer(pot); SPI.transfer(level); digitalWrite(ss, HIGH); }  void blinkAll(int count) { for (int z=0; z<count; z++) { allOn(); delay(1000); allOff(); delay(1000); } }  void indFade() { for (int a=0; a<4; a++) { for (int l=0; l<255; l++) { setPot(a,l); delay(del); } for (int l=255; l>=0; --l) { setPot(a,l); delay(del); } } }  void allFade(int count) { for (int a=0; a<count; a++) { for (int l=0; l<255; l++) { setPot(0,l); setPot(1,l); setPot(2,l); setPot(3,l); delay(del); } for (int l=255; l>=0; --l) { setPot(0,l); setPot(1,l); setPot(2,l); setPot(3,l); delay(del); } } }  void loop() { blinkAll(3); delay(1000); indFade(); allFade(3); }

The function allOff() and allOn() are used to set the potentiometers to minimum and maximum respectively. We use allOff() at the start of the sketch to turn the LEDs off. This is necessary as on power-up the wipers are generally set half-way. Furthermore we use them in the blinkAll() function to … blink the LEDs. The function setPot() accepts a wiper number (0~3) and value to set that wiper (0~255). Finally the function indFade() does a nice job of fading each LED on and off in order – causing an effect very similar to pulse-width modulation.

Finally, here it is in action:

Question – Would you use a rheostat or a potentiometer to divide voltage?

Example 34.3

In this example, we will use use a four-digit, seven-segment LED display that has an SPI interface. Using such a display considerably reduces the amount of pins required on the micro controller and also negates the use of shift register ICs which helps reduce power consumption and component count. The front of our example:

and the rear:

Thankfully the pins are labelled quite clearly. Please note that the board does not include header pins – they were soldered in after receiving the board. Although this board is documented by Sparkfun there seems to be issues in the operation, so instead we will use a sketch designed by members of the Arduino forum. Not wanting to ignore this nice piece of hardware we will see how it works and use it with the new sketch from the forum.

Again, wiring is quite simple:

  • Board GND to Arduino GND
  • Board VCC to Arduino 5V
  • Board SCK to Arduino D12
  • Board SI to Arduino D11
  • Board CSN to Arduino D10

The sketch is easy to use, you need to replicate all the functions as well as the library calls and variable definitions. To display numbers (or the letters A~F) on the display, call the function

write_led(a,b,c);

where a is the number to display, b is the base system used (2 for binary, 8 for octal, 10 for usual, and 16 for hexadecimal), and c is for padded zeros (0 =off, 1=on). If you look at the void loop() part of the example sketch, we use all four number systems in the demonstration. If your number is too large for the display, it will show OF for overflow. To control the decimal points, colon and the LED at the top-right the third digit, we can use the following:

write_led_decimals(1); // left-most decimal point write_led_decimals(2); write_led_decimals(4); write_led_decimals(8); // right-most decimal point write_led_decimals(16); // colon LEDs write_led_decimals(32); // apostrophe LED write_led_decimals(0); // off

After all that, here is the demonstration sketch for your perusal (download):

/* Example 34.3 - SPI bus demo using SFE 4-digit LED display [http://bit.ly/ixQdbT] http://tronixstuff.com/tutorials > chapter 34 Based on code by Quazar & Busaboi on Arduio forum - http://bit.ly/iecYBQ */  #define DATAOUT 11 //MOSI #define DATAIN 12 //MISO - not used, but part of builtin SPI #define SPICLOCK 13 //sck #define SLAVESELECT 10 //ss  char spi_transfer(volatile char data) { SPDR = data;                    // Start the transmission while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission { }; return SPDR;                    // return the received byte }  void setup() { byte clr; pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK, OUTPUT); pinMode(SLAVESELECT, OUTPUT); digitalWrite(SLAVESELECT, HIGH); //disable device SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1); clr=SPSR; clr=SPDR; delay(10); write_led_numbers(0x78,0x78,0x78,0x78); //Blank display write_led_decimals(0x00); // All decimal points off }  void write_led_decimals(int value) { digitalWrite(SLAVESELECT, LOW); delay(10); spi_transfer(0x77);     // Decimal Point OpCode spi_transfer(value);    // Decimal Point Values digitalWrite(SLAVESELECT, HIGH); //release chip, signal end transfer } void write_led_numbers(int digit1, int digit2, int digit3, int digit4) { digitalWrite(SLAVESELECT, LOW); delay(10); spi_transfer(digit1);    // Thousands Digit spi_transfer(digit2);    // Hundreds Digit spi_transfer(digit3);    // Tens Digit spi_transfer(digit4);    // Ones Digit digitalWrite(SLAVESELECT, HIGH); //release chip, signal end transfer }  void write_led(unsigned short num, unsigned short base, unsigned short pad) { unsigned short digit[4] = { 0, ' ', ' ', ' '     }; unsigned short place = 0;  if ( (base<2) || (base>16) || (num>(base*base*base*base-1)) ) { write_led_numbers(' ', 0x00, 0x0f, ' ');  // indicate overflow } else { while ( (num || pad) && (place<4) ) { if ( (num>0)  || pad ) digit[place++] = num % base; num /= base; } write_led_numbers(digit[3], digit[2], digit[1], digit[0]); } }  void pointDemo() { write_led_decimals(1); delay(1000); write_led_decimals(2); delay(1000); write_led_decimals(4); delay(1000); write_led_decimals(8); delay(1000); write_led_decimals(16); delay(1000); write_led_decimals(32); delay(1000); write_led_decimals(0); // non-digits all off }  void loop() { pointDemo(); delay(500); for (int i = 0; i < 100; i++) { write_led (i,10,1); delay(25); } delay(500); for (int i = 100; i >=0; --i) { write_led (i,10,0); delay(25); } delay(500); // now binary for (int i = 0; i < 16; i++) { write_led (i,2,0); delay(100); } delay(500); for (int i = 15; i >=0; --i) { write_led (i,2,0); delay(100); } delay(500); // now octal for (int i = 0; i < 500; i++) { write_led (i,8,0); delay(50); } delay(500); // now hexadecimal for (int i = 20000; i < 22000; i++) { write_led (i,16,0); delay(50); } delay(500); }

And a short video of the demonstration:

So there you have it – hopefully an easy to understand introduction to the world of the SPI bus and how to control the devices within. As always, now it is up to you and your imagination to find something to control or get up to other shenanigans. In the next SPI article we will look at reading and writing data via the SPI bus. If you have any suggestions with regards to parts for the next article, leave a comment below and we’ll look into it.  Thank you for your patience in awaiting this series of articles. Although getting it together was a little tricky, it was a lot of fun. I hope you enjoyed reading it as much as I did writing it for you.

If you have any questions about the processes or details in this article, please ask in our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, there is the odd competition or give-away –  and we can all learn something. Or follow tronixstuff on twitter and facebook. High resolution images available on flickr.

Otherwise, have fun, stay safe, be good to each other – and make something!

Friday, May 13, 2011

Kit review – nootropic design Hackvision

Hello readers

Time for another kit review – the nootropics design Hackvision a nice change from test equipment. The purpose of the Hackvision is to allow the user to create retro-style arcade games and so on that can be played on a monitor or television set with analogue video input. Although the display resolution is only 128 by 96 pixels, this is enough to get some interesting action happening. Frankly I didn’t think the Arduino hardware environment alone was capable of this, so the Hackvision was a pleasant surprise.

Assembly is quick and relatively simple, the instructions are online and easy to follow. All the parts required are included:

The microcontroller is pre-loaded with two games so you can start playing once construction has finished. However you will need a 5V FTDI cable if you wish to upload new games as the board does not have a USB interface. The board is laid out very clearly, and with the excellent silk-screen and your eyes open construction will be painless. Note that you don’t need to install R4 unless necessary, and if your TV system is PAL add the link which is between the RCA sockets. Speaking of which, when soldering them in, bend down the legs to lock them in before soldering, as such:

Doing so will keep them nicely flush with the PCB whilst soldering. Once finished you should have something like this:

All there is to do now is click the button covers into place, plug in your video and audio RCA leads to a monitor, insert nine volts of DC power, and go:

Nice one. For the minimalist users out there, be careful if playing games as the solder on the rear of the PCB can be quite sharp. Included with the kit is some adhesive rubber matting to attach to the underside to smooth everything off nicely. However only fit this once you have totally finished with soldering and modifying the board, otherwise it could prove difficult to remove neatly later on. Time to play some games… in the following video you can see how poor my reflexes are when playing Pong and Space Invaders:

... the Hackvision also generates sounds, however my cheap $10 video capture dongle from eBay didn't come through with the audio ... ]

Well that takes me back. There are some more contemporary games and demonstration code available on the Hackvision games web page. For the more involved Hackvision gamer, there are points on the PCB to attach your own hand-held controls such as paddles, nunchuks and so on. There is a simple tutorial on how to make your own paddles here.

Those who have been paying attention will have noticed that although the Hackvision PCB is not the standard Arduino Duemilanove-compatible layout, all the electronics are there. Apart from I/O pins used by the game buttons, you have a normal Arduino-style board with video and audio out. This opens up a whole world of possibilities with regards to the display of data in your own Arduino sketches (software). From a power supply perspective, note that the regulator is a 78L05 which is only good for 100mA of current, and the board itself uses around 25mA.

Question – Who invented the video game Pong?

To control the video output, you will need to download and install the hackvision-version arduino-tvout library. Note that this library is slightly different to the generic arduino-tvout library with regards to function definitions and parameters. To make use of the included buttons easier, there is also the controllers library. Here is a simple, relatively self-explanatory sketch that demonstrates some uses of the tvout functions (download):

/* nootropics Hackvision display demo two http://tronixstuff.wordpress.com > kit reviews John Boxall 13 May 2011 | CC by-sa */  #include #include #include #include #include   int x,y=0; int d=500; // used for various delays // declare screen resolution #define W 136 #define H 98  // create instance of TV TVout tv;  void setup()  {  // If pin 12 is pulled LOW, then the PAL jumper is shorted. pinMode(12, INPUT); digitalWrite(12, HIGH);  if (digitalRead(12) == LOW) { tv.begin(_PAL, W, H); // Since PAL processing is faster, we need to slow the game play down. } else { tv.begin(_NTSC, W, H); } randomSeed(analogRead(0)); }  void randomPixels() { tv.clear_screen(); // clears the screen for (int a=0; a<500; a++) { x=random(128); y=random(96); tv.set_pixel(x,y,1); // 1 for white, 0 for black, 2 for inverse of current colour at that location delay(10); } }  void randomLines() { tv.clear_screen(); // clears the screen for (int a=0; a<128; a++) { tv.draw_line(a,1,a,96,1); // x,y to x,y, colour 1 = white delay(50); } }  void rectangles() { tv.clear_screen(); // clears the screen for (int a=0; a<30; a++) { x=random(128); y=random(96); tv.draw_box(x,y,x+10,y+10,1,0,0,1); // top-left x,y, length, width, colour, fill (0 = no, 1 = yes) delay(50); tv.draw_box(x,y,x+10,y+10,1,1,0,1); // top-left x,y, length, width, colour, fill (0 = no, 1 = yes) delay(50); } }  void circles() { tv.clear_screen(); // clears the screen for (int a=0; a<30; a++) { x=random(128); y=random(96); tv.draw_circle(x,y,a,1,0,1); // x,y coordinates, radius, line colour, fill delay(50); tv.draw_circle(y,x,a,1,1,1); delay(50); } }  void loop() { randomPixels(); delay(d); randomLines(); delay(d); rectangles(); delay(d); circles(); delay(d); }

And the resulting video demonstration:

I will be the first to admit that my imagination is lacking some days. However with the sketch above hopefully you can get a grip on how the functions work. But there are some very good game implementations out there, as listed on the Hackvision games page. After spending some time with this kit, I feel that there is a lack of documentation that is easy to get into. Sure, having some great games published is good but some beginners’ tutorials would be nice as well. However if you have the time and the inclination, there is much that could be done. In the meanwhile you can do your own sleuthing with regards to the functions by examining the TVout.cpp file in the Hackvision tvout library folder.

For further questions about the Hackvision contact nootropic design or perhaps post on their forum. However the Hackvision has a lot of potential and is an interesting extension of the Arduino-based hardware universe – another way to send data to video monitors and televisions, and play some fun games. The Hackvision is available from Little Bird Electronics. If you are looking for a shield-based video output device, perhaps consider the Batsocks Tellymate.

As always, thank you for reading and I look forward to your comments and so on. Furthermore, don’t be shy in pointing out errors or places that could use improvement. Please subscribe using one of the methods at the top-right of this web page to receive updates on new posts, follow me on twitter or facebook, or join our Google Group for further discussion.

High resolution images are available on flickr.

[Note - The kit was purchased by myself personally and reviewed without notifying the manufacturer or retailer]

Otherwise, have fun, be good to each other – and make something! 

Tuesday, May 10, 2011

Discovering Arduino’s internal EEPROM lifespan

Hello readers

Some time ago I published a short tutorial concerning the use of the internal EEPROM  belonging to the Atmel ATmega328 (etc.) microcontroller in our various Arduino boards. Although making use of the EEPROM is certainly useful, it has a theoretical finite lifespan - according to the Atmel data sheet (download .pdf) it is 100,000 write/erase cycles.

One of my twitter followers asked me "is that 100,000 uses per address, or the entire EEPROM?" - a very good question. So in the name of wanton destruction I have devised a simple way to answer the question of EEPROM lifespan. We will write the number 170 (10101010 in binary) to each EEPROM address, then read each EEPROM address to check the stored number. The process is then repeated by writing the number 85 (01010101 in binary) to each address and then checking it again. The two binary numbers were chosen to ensure each bit in an address has an equal number of state changes.

After both of the processes listed above has completed, then the whole lot repeats. The process is halted when an incorrectly stored number is read from the EEPROM - the first failure. At this point the number of cycles, start and end time data are shown on the LCD.

Question - What is the largest integer that can be stored in an ATmega328 EEPROM address?

In this example one cycle is 1024 sequential writes then reads. One would consider the entire EEPROM to be unusable after one false read, as it would be almost impossible to keep track of  individual damaged EEPROM addresses. (Then again, a sketch could run a write/read check before attempting to allocate data to the EEPROM...)

If for some reason you would like to run this process yourself, please do not do so using an Arduino Mega, or another board that has a fixed microcontroller. (Unless for some reason you are the paranoid type and need to delete some data permanently). Once again, please note that the purpose of this sketch is to basically destroyyour Arduino's EEPROM. Here is the sketch (download):

/* Arduino EEPROM killer John Boxall - http://tronixstuff.com - March 2011 CC by-sa Note: This sketch will destroy your Arduino's EEPROM Do not use with Arduino boards that have fixed microcontrollers Sketch assumes DS1307 already contains current date and time */  #include <EEPROM.h> #include <LiquidCrystal.h> LiquidCrystal lcd(4,5,6,7,8,9);  #include "Wire.h" #define DS1307_I2C_ADDRESS 0x68  // all these bytes necessary for time and date data byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; byte sday, smonth, ssecond, sminute, shour; byte fday, fmonth, fsecond, fminute, fhour;  // to store number of cycles. Should be enough long cycles=0; // maximum size is 2,147,483,647  int zz=0;  void setup() { lcd.begin(16, 2); // fire up the LCD Wire.begin(); // and the I2C bus }  // Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); }  // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }  // Gets the date and time from the ds1307 void getDateDs1307(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { // Reset the register pointer Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.send(0); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 7);  // A few of these need masks because certain bits are control bits *second     = bcdToDec(Wire.receive() & 0x7f); *minute     = bcdToDec(Wire.receive()); *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm *dayOfWeek  = bcdToDec(Wire.receive()); *dayOfMonth = bcdToDec(Wire.receive()); *month      = bcdToDec(Wire.receive()); *year       = bcdToDec(Wire.receive()); }  void killEEPROM() { boolean dead=false; // record start time getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); sday=dayOfMonth; smonth=month; ssecond=second; sminute=minute; shour=hour; lcd.clear(); lcd.setCursor(0,0); lcd.print("Cycles so far..."); do // write and read EEPROM addresses until the first failure { for (int a=0; a<1024; a++) { EEPROM.write(a, 170); // write binary 10101010 to each EEPROM address } for (int a=0; a<1024; a++) // check each address { zz = EEPROM.read(a); if (zz!=170) { dead=true; // uh-oh, an address has died cycles-=2; // easy way out to calculate cycles once died } } cycles++; lcd.setCursor(0,1); lcd.print(cycles); for (int a=0; a<1024; a++) { EEPROM.write(a, 85); // write binary 01010101 to each EEPROM address } for (int a=0; a<1024; a++) // check each address { zz = EEPROM.read(a); if (zz!=85) { dead=true; // uh-oh, an address has died --cycles; // easy way out to calculate cycles once died } } cycles++; lcd.setCursor(0,1); lcd.print(cycles); // update the LCD } while (dead!=true); // so now one address write/read has failed, the game's up // record end time getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); fday=dayOfMonth; fmonth=month; fsecond=second; fminute=minute; fhour=hour; // display final statistics (endless loop) do { lcd.clear(); lcd.setCursor(0,0); lcd.print("Start date/time: "); lcd.setCursor(1,1); lcd.print(sday, DEC); lcd.print("/"); lcd.print(smonth, DEC); lcd.print(" "); lcd.print(shour, DEC); lcd.print(":"); if (sminute<10) { lcd.print("0"); } lcd.print(sminute, DEC); lcd.print(":"); if (ssecond<10) { lcd.print("0"); } lcd.print(ssecond, DEC); delay(2000); lcd.clear(); lcd.setCursor(0,0); lcd.print("End date/time: "); lcd.setCursor(1,1); lcd.print(fday, DEC); lcd.print("/"); lcd.print(fmonth, DEC); lcd.print(" "); lcd.print(fhour, DEC); lcd.print(":"); if (fminute<10) { lcd.print("0"); } lcd.print(fminute, DEC); lcd.print(":"); if (fsecond<10) { lcd.print("0"); } lcd.print(fsecond, DEC); delay(2000); lcd.clear(); lcd.setCursor(0,0); lcd.print("  # of cycles:"); lcd.setCursor(0,1); lcd.print(cycles); delay(2000); } while(1>0); }  void loop() { // nice intro display with countdown lcd.clear(); lcd.setCursor(0,0); lcd.print("EEPROM Destroyer"); lcd.setCursor(0,1); for (int a=99; a>0; --a) // gives user 99 seconds to change mind before start { lcd.setCursor(0,1); lcd.print("Starting in "); lcd.print(a); lcd.print("s "); delay(995); } lcd.clear(); killEEPROM(); }

If you are unfamiliar with the time-keeping section, please see part one of my Arduino+I2C tutorial. The LCD used was my quickie LCD shield - more information about that here. A quicker, painless option would be a Freetronics 16x2 LCD shield as tested here. Or you could always just send the data to the serial monitor box - however you would need to leave the PC on for a loooooong time... So instead the example sat on top of an AC adaptor (wall wart) behind a couch (sofa)  for a couple of months:

The only catch with running it from AC was the risk of possible power outages. We had one planned outage when our house PV system was installed, so I took a count reading before the mains was turned off, and corrected the sketch before starting it up again after the power cut. Nevertheless, here is a short video - showing the start and the final results of the test:

[youtube=http://www.youtube.com/watch?v=t8X0zip7TvU]

So there we have it, 1230163 cycles with each cycle writing and reading each individual EEPROM address. If repeating this odd experiment, your result will vary.

Well I hope someone out there found this interesting. Please refrain from sending emails or comments criticising the waste of a microcontroller - this was a one off. Otherwise, to keep up with new activities here at tronixtuff please subscribe to the blog, RSS feed (top-right), twitter or joining our Google Group.

If you have any questions about the processes or details in this article, please ask in our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, there is the odd competition or give-away –  and we can all learn something.

Otherwise, have fun, stay safe, be good to each other – and make something!