Posts with «lesson» label

First look – Arduino Yún

Introduction

After being announced in May this year, the new Arduino Yún has arrived in the crowded marketplace – and I snapped up one of the first to arrive in Australia for an initial review. The purpose of which is to run through the out of box experience, and to see how easy it was to get the Yún working with the promised new features.

[Update – over time we’ll publish tutorials specifically for the Yún, which are listed here.]

The Yún introduces some interesting new combinations of hardware and connectivity, all within the familiar form-factor. Which gives us plenty to examine and write about, so let’s get started. First, a quick look around the Yún:

Notice the stickers on the header sockets, useful for beginners or the absent-minded…

The usual TX/RX and D13 LEDs, plus notifiers for power, WiFi, LAN and USB use…

Ethernet, USB programming, USB host…

Again with the stickers…

The rear is quite busy. You can also see “Made in Taiwan” – a first for Arduino. I believe the reason for this was due to the new Atheros chipset requirements. Did you notice the multiple reset buttons? There are three – one for the Arduino, one for wifi and one to reboot Linino. As you can see there’s a lot of circuity on the bottom of the Yún, so it would be prudent to use some short standoffs to elevate the board and protect the bottom. Before moving on, you might like the following video where the Arduino team introduce the Yún:

Specifications

The Yún is based around the Arduino Leonardo-specification board – thus you have the ATmega32U4 microcontroller and the usual Leonardo functions. Note you cannot feed wild DC voltages into the Vin pin – it must be a regulated 5V. And the DC socket has gone, so for a solid connection you might want to make or buy your own power shield.

However there is so much more… underneath a small metal shield below the digital I/O pins is an Atheros AR9331 CPU running a Linux distribution based on OpenWRT named Linino. This Atheros part of the board is connected to a microSD socket, 10/100 Ethernet port, a USB 2.0 socket for host-mode functions and also has IEEE 802.11b/g/n WiFi, and Power-over-Ethernet support (with an optional adaptor).

And all of that is connected to the Arduino side of things via a simple serial “bridge” connection (with it’s own library) – which gives the Arduino side of the board very simple methods of controlling the other onboard hardware.

Getting started with the Yún WiFi

First thing is to download and install the new IDE, version 1.5.4. This is for Due and Yún, so keep your older installations as well. On the general Arduino side of things nothing has changed, so we’ll move on to the more interesting side of the board. The first of these is to setup and experiment with the onboard WiFi. After connecting your board to USB for power, you can connect to it with your PC’s WiFi:

… at which point you connect to the Yún network. Then visit 192.168.240.1 from a web browser, and you’re presented with a page that asks for the default password, which is … “arduino”:

At which point you’re presented with the relevant details for your Yún:

… such as the IP address, MAC address, etc. Make note of your MAC address, you might need it later. From here you can configure the Yún WiFi details, for example the name and password, and also the details of your existing WiFi network which can be used to access the Yún. Once you save those, the Yún reboots and tells you to connect the PC back to the existing WiFi network:

If for some reason it doesn’t work or you entered the wrong settings – hold down the “WLAN RST” button (next to the USB host socket) for five seconds. This sets the WiFi details in the Yun back to the default … and you can start all over again.

Note that the Yún’s preset IP of 192.168.240.1 may not be suitable for your own network. For example, if your home router is 10.1.1.1 you need to do some detective work to find out the IP address for the Yún. Head into your router’s administration pages and look for your DHCP Client Log. It will show a list of devices that are connected to the network, including their MAC and IP address – for example:

Then it’s a simple matter of finding the MAC address in the list and the matching IP. Once you have the IP address, enter that into a web browser and after being prompted for the Yún’s password, you’re back to the welcome page with the IP, MAC addresses etc.

WiFi Sketch Uploading

Once your Yún is on the same WiFi network as the PC running the IDE – you can upload a sketch over WiFi! This is possible due to the bridge between the Atheros section on the board and the Arduino hardware. Just select the board type as normal in the IDE, and the port (the IP address version):

… then hit Upload as normal, enter the password:

and you’re done. Awesome.

Console-based control of Arduino over WiFi

There’s a neat example that demonstrates how you can control the Arduino over the WiFi using a console terminal on the PC. Upload this sketch (from http://arduino.cc/en/Guide/ArduinoYun#toc13):

#include <Console.h>

const int ledPin = 13; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup() {
  // initialize serial communication:
  Bridge.begin();
  Console.begin(); 

  while (!Console){
    ; // wait for Console port to connect.
  }
  Console.println("You're connected to the Console!!!!");
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // see if there's incoming serial data:
  if (Console.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByte = Console.read();
    // if it's a capital H (ASCII 72), turn on the LED:
    if (incomingByte == 'H') {
      digitalWrite(ledPin, HIGH);
    } 
    // if it's an L (ASCII 76) turn off the LED:
    if (incomingByte == 'L') {
      digitalWrite(ledPin, LOW);
    }
  }
}

Then load your terminal software. We use PuTTY on Windows. Run the terminal software, then login as root, then telnet to “localhost 6571”:

You can then send characters to the Yún just as you would with a USB-connected Arduino via the serial monitor. With the example above you’re turning the D13 LED on and off, but you can get the idea.

The “Internet of Things”

Arduino has teamed up with a service called “Temboo” – which gives you over 100 APIs that your Yún can hook up with to do a myriad of things, such as send tweets, get weather data from Yahoo, interact with Dropbox, etc. This is done easily and explained quite well at the Temboo website. After signing up for Temboo (one account seems to be free at the moment) we tried the Yahoo weather API.

You enter the parameters using an online form in Temboo (in our example, the address of the area whose weather forecast we required), and the Temboo site gives you the required Arduno sketch and header file to upload. And you’re done. With this particular example, I wanted the weather in Sydney CBD – and once running the data is returned to the serial monitor, for example:

It was great to see that work the very first time, and a credit to Temboo and Arduino for making it happen. But how?

There is a Temboo client in the Linino OS, which is the gateway to the API via WiFi, and also communicates with the Arduino via the serial bridge. The Arduino Temboo library can then interact with the Linino client without complex code. The weather data is then returned back from the Internet via the Temboo client and fed to the Arduino serial port, where you can parse it with your own code. This looks like a lot of fun, and also could be quite useful – for example capturing data and sending it to a Google Docs spreadsheet. For more information, check out the Temboo website.

However you can delve deeper and create your own APIs, matching code – and perhaps other services will develop their own APIs in the near future. But for now, it’s a good start.

Where to from here? And support?

This article has only scratched the surface (but not bad considering the board arrived a few hours ago). There’s plenty more examples on the getting started page, in the IDE (under “Bridge”) – plus a dedicated Arduino Yún forum. And check out this gmail notifier. In the near future we’ll create some of our own tutorials, so stay tuned.

Is the Yún a completely open-source product? 

Well it says “open source electronics prototyping platform” on the rear, but is this true? The Arduino Leonardo-side of the board is. However the Atheros AR9331 chip is not. Nevertheless, are you really going to reproduce your own AR9331? So it doesn’t really matter. Being a pragmatist I propose that the Yún solves the problem of Arduino and Internet connectivity quite well for the non-advanced user – so not being totally OSHW isn’t an issue.

Support

This board is very new to us here, so for questions or support please ask on the dedicated Arduino Yún forum.

Conclusion

Since the popularity of various single-board computers has increased exponentially over the last few months, some may say that the Yún is perhaps too little, too late. After only having the Yún for a few hours before writing this article, personally I disagree with this statement – the Yún is a device that still gives us the wide range of hardware control, and what looks to be a very simple method of connectivity that surely is cheaper and less prone to issues than the original Arduino WiFi shield.

What the Yún gives us is a simple, well-executed method of getting our Arduino connected to the outside world – and in a manner that won’t confuse or put off the beginner or intermediate user. So for now, it’s a win.

What do you think? Leave a comment below.

And for more detail, full-sized images from this article can be found on flickr. And if you’re interested in learning more about Arduino, or want to introduce someone else to the interesting world of Arduino – check out my book (now in a third printing!) “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post First look – Arduino Yún appeared first on tronixstuff.

Tronixstuff 18 Sep 14:39

Tutorial – Arduino and SIM900 GSM Modules

Use the SIM900 GSM modules with Arduino in Chapter 55 of our Arduino Tutorials. The first chapter is here, the complete series is detailed here.

Introduction

The goal of this tutorial is to illustrate various methods of interaction between an Arduino Uno (or compatible) and the GSM cellular network using a SIM900 GSM shield, with which you can then use your existing knowledge to build upon those methods.

We’ll be using a SIMCOM SIM900 GSM module shield. (If you’re looking for tutorials on the Spreadtrum SM5100 modules, start here). There must be scores of Arduino shields or modules using the SIM900, so as you can imagine each one may be a little bit different with regards to the hardware side of things – so we’re assuming you have an understanding of how hardware and software serial works as well as supply voltages and the hardware side of the Arduino world.

As for the specific shield to use, we just chose the cheapest one available at the time – which turned out to be the “SIM900 GPRS/GSM Arduino shield” from Linksprite:

However with a little research and work, the sketches provided should also work with any SIM900 module/shield and Arduino – as long as you have the appropriate serial and power settings. 

Getting Started

A little preparation goes a long way, so make sure you’ve covered the following points:

  • Regarding your cellular provider. Do you have coverage on a GSM 850 MHz, GSM 900 MHz, DCS 1800 MHz or PCS 1900 MHz network?  When we say GSM that means 2G – not 3G, 4G or LTE. Will they allow the use of non-supported devices on the network? Some carriers will block IMEI numbers that were not provided by their sales channel. Or you may have to call the provider and supply the IMEI of your GSM module to allow it on the network. Finally, it would be wise to use either a prepaid or an account that offers unlimited SMS text messaging – you don’t want any large bills if things go wrong.
  • Power. Do you have adequate power for your SIM900 module? Some shields will use more current than the Arduino can supply (up to 2A), so you may need an external high-current supply. The Linksprite shield we use needs 5V up to 2A into the onboard DC socket. Otherwise, check with your supplier.
  • Antenna. If your module/shield etc. doesn’t have an antenna – get one. You do need it.
  • Turn off the PIN lock on the SIM card. The easiest way to do this is to put the SIM in a handset and use the menu function.
  • And as always, please don’t make an auto-dialler…

Furthermore, download the SIM900 hardware manual (.pdf) and the AT command manual (.pdf), as we’ll refer to those throughout the tutorial.

Power

There is a DC socket on the shield, which is for a 5V power supply:

Although the data from Linksprite claims the shield will use no more than 450 mA, the SIMCOM hardware manual (page 22) for the module notes that it can draw up to 2A for short bursts. So get yourself a 5V 2A power supply and connect it via the DC socket, and also ensure the switch next to the socket is set to “EXT”.

Furthermore, you can turn the GSM module on and off with the power button on the side of the shield, and it defaults to off during an initial power-up. Therefore you’ll need to set D9 to HIGH for one second in your sketch to turn the module on (or off if required for power-saving). Don’t panic, we’ll show how this is done in the sketches below.

Software Serial

We will use the Arduino software serial library in this tutorial, and the Linksprite shield has hard-wired the serial from the SIM900 to a set of jumpers, and uses a default speed of 19200. Make sure you your jumpers are set to the “SWserial” side, as shown below:

And thus whenever an instance of SoftwareSerial is created, we use 7,8 as shown below:

SoftwareSerial SIM900(7, 8); // RX, TX

If you shield is different, you’ll need to change the TX and RX pin numbers. This also means you can’t use an Arduino Leonardo or Mega (easily).

Wow – all those rules and warnings?

The sections above may sound a little authoritarian, however we want your project to be a success. Now, let’s get started…

A quick test…

At this point we’ll check to make sure your shield and locate and connect to the cellular network. So make sure your SIM card is active with your cellular provider, the PIN lock is off, and then insert it and lock the SIM card  to the carrier on the bottom of the shield:

Then plug the shield into your Uno, attach 5V power to the DC socked on the GSM shield, and USB from the Uno to the PC. Press the “PWRKEY” button on the side of the shield for a second, then watch the following two LEDs:

The bright “STATUS” LED will come on, and then the “NETLIGHT” LED will blink once every 800 milliseconds- until the GSM module has found the network, at which point it will blink once every three seconds. This is shown in the following video:

Nothing can happen until that magic three-second blink – so if that doesn’t appear after a minute, something is wrong. Check your shield has the appropriate power supply, the antenna is connected correctly, the SIM card is seated properly and locked in- and that your cellular account is in order. Finally, you may not have reception in that particular area, so check using a phone on the same network or move to a different location.

Making a telephone call from your Arduino

You can have your Arduino call a telephone number, wait a moment – then hang up. This is an inexpensive way of alerting you of and consider the following sketch:

// Example 55.1

#include <SoftwareSerial.h>
SoftwareSerial SIM900(7, 8); // configure software serial port

void setup()
{
  SIM900.begin(19200);               
  SIM900power();  
  delay(20000);  // give time to log on to network. 
}

void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(5000);
}

void callSomeone()
{
  SIM900.println("ATD + +12128675309;"); // dial US (212) 8675309
  delay(100);
  SIM900.println();
  delay(30000);            // wait for 30 seconds...
  SIM900.println("ATH");   // hang up
}

void loop()
{
  callSomeone(); // call someone
  SIM900power();   // power off GSM shield
  do {} while (1); // do nothing
}

The sketch first creates a software serial port, then in void setup() starts the software serial port, and also turns on the GSM shield with the function SIM900power (which simply sets D9 high for a second which is the equivalent of pressing the power button). Notice the delay function in void setup – this gives the GSM module a period of time to locate and log on to the cellular network. You may need to increase (or be able to decrease) the delay value depending on your particular situation. If in doubt, leave it as a long period.

The process of actually making the call is in the function callSomeone(). It sends a string of text to the GSM module which consists of an AT command. These are considered the “language” for modems and thus used for various tasks. We use the ATD command to dial (AT… D for dial) a number. The number as you can see in the sketch needs to be in world-format. So that’s a “+” then the country code, then the phone number with area code (without the preceding zero).

So if your number to call is Australia (02) 92679111 you would enter +61292679111. Etcetera. A carriage return is then sent to finalise the command and off it goes dialling the number. Here’s a quick video demonstration for the non-believers:

After thirty seconds we instruct the module to hand up with another AT command – “ATH” (AT… H for “hang up”), followed by turning off the power to the module. By separating the call feature into a function – you can now insert this into a sketch (plus the preceding setup code) to call a number when required.

Sending an SMS text message

This is a great way of getting data from your Arduino to almost any mobile phone in the world, at a very low cost. For reference, the maximum length of an SMS text message is 160 characters – however you can still say a lot with that size limit. First we’ll demonstrate sending an arbitrary SMS. Consider the following sketch:

// Example 55.2

#include <SoftwareSerial.h>
SoftwareSerial SIM900(7, 8);

void setup()
{
  SIM900.begin(19200);
  SIM900power();  
  delay(20000);  // give time to log on to network. 
}

void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(5000);
}

void sendSMS()
{
  SIM900.print("AT+CMGF=1\r");                                                        // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"+12128675309\"");                                     // recipient's mobile number, in international format
  delay(100);
  SIM900.println("Hello, world. This is a text message from an Arduino Uno.");        // message to send
  delay(100);
  SIM900.println((char)26);                       // End AT command with a ^Z, ASCII code 26
  delay(100); 
  SIM900.println();
  delay(5000);                                     // give module time to send SMS
  SIM900power();                                   // turn off module
}

void loop()
{
  sendSMS();
  do {} while (1);
}

The basic structure and setup functions of the sketch are the same as the previous example, however the difference here is the function sendSMS(). It used the AT command “AT+CMGF” to tell the GSM module we want to send an SMS in text form, and then “AT+CMGS” followed by the recipient’s number. Once again note the number is in international format. After sending the send SMS commands, the module needs  five seconds to do this before we can switch it off. And now for our ubiquitous demonstration video:

 

You can also send text messages that are comprised of numerical data and so on – by compiling the required text and data into a string, and then sending that. Doing so gives you a method to send such information as sensor data or other parameters by text message.

For example, you might want to send daily temperature reports or hourly water tank levels. For our example, we’ll demonstrate how to send a couple of random numbers and some text as an SMS. You can then use this as a framework for your own requirements. Consider the following sketch:

// Example 55.3

#include <SoftwareSerial.h>
SoftwareSerial SIM900(7, 8);
int x,y;
String textForSMS;

void setup()
{
  SIM900.begin(19200);
  SIM900power();  
  delay(20000);  // give time to log on to network. 
  randomSeed(analogRead(0));
}

void SIM900power()
// software equivalent of pressing the GSM shield "power" button
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(7000);
}

void sendSMS(String message)
{
  SIM900.print("AT+CMGF=1\r");                     // AT command to send SMS message
  delay(100);
  SIM900.println("AT + CMGS = \"+12128675309\"");  // recipient's mobile number, in international format
  delay(100);
  SIM900.println(message);                         // message to send
  delay(100);
  SIM900.println((char)26);                        // End AT command with a ^Z, ASCII code 26
  delay(100); 
  SIM900.println();
  delay(5000);                                     // give module time to send SMS
  SIM900power();                                   // turn off module
}

void loop()
{
  x = random(0,255);
  y = random(0,255);
  textForSMS = "Your random numbers are ";
  textForSMS.concat(x);
  textForSMS = textForSMS + " and ";
  textForSMS.concat(y);
  textForSMS = textForSMS + ". Enjoy!";  
  sendSMS(textForSMS);
  do {} while (1);
}

Take note of the changes to the function sendSMS(). It now has a parameter – message, which is a String which contains the text to send as an SMS. In void loop() the string variable textForSMS is constructed. First it contains some text, then the values for x and y are added with some more text. Finally the string is passed to be sent as an SMS. And here it is in action:

Conclusion

After working through this tutorial you should have an understanding of how the basics of the GSM shield and AT commands work. If there’ s demand we’ll continue with more features and possibilities in a future tutorial, so let us know via the contact page.  And if you enjoyed the tutorial, or want to introduce someone else to the interesting world of Arduino – check out my book (now in a third printing!) “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Tutorial – Arduino and SIM900 GSM Modules appeared first on tronixstuff.

Tronixstuff 18 Sep 03:33

Tutorial – Arduino and the TI ADS1110 16-bit ADC

Learn how to use the TI ADS1110 16-bit ADC with Arduino in chapter fifty-three of my Arduino Tutorials. The first chapter is here, the complete series is detailed here.

Updated 02/07/2013

Introduction

Moving on from the last chapter where we explained an 8-bit ADC, in this instalment we have the Texas Instruments ADS1110 – an incredibly tiny but useful 16-bit analogue-to-digital converter IC.  It can operate between 2.7 and 5.5 V so it’s also fine for Arduino Due and other lower-voltage development boards. This is a quick guide to get you going with the ADS1110 ready for further applications. Before continuing any further, please download the data sheet (pdf) as it will be useful and referred to during this tutorial. The ADS1110 gives you the option of a more accurate ADC than offered by the Arduino’s 10-bit ADCs – and it’s relatively easy to use. The only block for some is the package type – it’s only available in SOT23-6:

So unless you’re making a customised PCB, some sort of breakout will be required. One useful example is the Schmartboard we reviewed earlier:

The ADS1110 uses the I2C bus for communication, so if this is new to you – please review the I2C tutorials before continuing. And as there’s only six pins you can’t set the bus address – instead, you can select from six variants of the ADS1110 – each with their own address (see page two of the data sheet). As you can see the in the photo above, ours is marked “EDO” which matches to the bus address 1001000 or 0x48h. And with the example circuits we’ve used 10kΩ pull-up resistors on the I2C bus. You can use the ADS1110 as either a single-ended or differential ADC –  But first we need to examine the configuration register which is used to control various attributes, and the data register.

Configuration register

Turn to page eleven of the data sheet. The configuration register is one byte in size, and as the ADS1110 resets on a power-cycle – you need to reset the register if your needs are different to the defaults. The data sheet spells it out quite neatly… bits 0 and 1 determine the gain setting for the PGA (programmable gain amplifier). If you’re just measuring voltages or experimenting, leave these as zero for a gain of 1V/V. Next, the data rate for the ADS1110 is controlled with bits 2 and 3. If you have continuous sampling turned on, this determines the number of samples per second taken by the ADC.

After some experimenting with an Arduino Uno we found the values returned from the ADC were a bit off when using the fastest rate, so leave it as 15 SPS unless required otherwise. Bit 4 sets either continuous sampling (0) or one-off sampling (1). Ignore bits 5 and 6, however they’re always set as 0. Finally bit 7 – if you’re in one-off sampling mode, setting it to 1 requests a sample – and reading it will tell you if the returned data is new (0) or old (1). You can check that the value measured is a new value – if the first bit of the configuration byte that comes after the data is 0, it’s new. If it returns 1 the ADC conversion hasn’t finished.

Data register

As the ADS1110 is a 16-bit ADC, it returns the data over two bytes – and then follows with the value of the configuration register. So if you request three bytes the whole lot comes back. The data is in “two’s complement” form, which is a method of using signed numbers with binary. Converting those two bytes is done by some simple maths. When sampling at 15 SPS, the value returned by the ADS1110 (not the voltage)  falls between -32768 and 32767. The higher byte of the value is multiplied by 256, then added to the lower byte – which is then multiplied by 2.048 and finally divided by 32768. Don’t panic, as we do this in the example sketch below.

Single-ended ADC mode

In this mode you can read a voltage that falls between zero and 2.048 V (which also happens to be the inbuilt reference voltage for the ADS1110). The example circuit is simple (from the data sheet):

Don’t forget the 10kΩ pull-up resistors on the I2C bus. The following sketch uses the ADS1110 in the default mode, and simply returns the voltage measured:

// Example 53.1 - ADS1110 single-sided voltmeter (0~2.048VDC)

#include "Wire.h"
#define ads1110 0x48
float voltage, data;
byte highbyte, lowbyte, configRegister;
void setup()
{
 Serial.begin(9600);
 Wire.begin();
}
void loop()
{
 Wire.requestFrom(ads1110, 3);
 while(Wire.available()) // ensure all the data comes in
 {
 highbyte = Wire.read(); // high byte * B11111111
 lowbyte = Wire.read(); // low byte
 configRegister = Wire.read();
 }

 data = highbyte * 256;
 data = data + lowbyte;
 Serial.print("Data >> ");
 Serial.println(data, DEC);
 Serial.print("Voltage >> ");
 voltage = data * 2.048 ;
 voltage = voltage / 32768.0;
 Serial.print(voltage, DEC);
 Serial.println(" V");
 delay(1000);
}

Once uploaded, connect the signal to measure and open the serial monitor – you’ll be presented with something similar to:

If you need to alter the gain of the internal programmable gain amplifier of the ADC – you’ll need to write a new byte into the configuration register using:

Wire.beginTransmission(ads1110);
Wire.write(configuration byte); 
Wire.endTransmission();

before requesting the ADC data. This would be 0x8D, 0x8E or 0x8F for gain values of 2, 4 and 8 respectively – and use 0x8C to reset the ADS1110 back to default.

Differential ADC mode

In this mode you can read the difference between two voltages that each fall between zero and 5 V. The example circuit is simple (from the data sheet):

We must note here (and in the data sheet) that the ADS1110 can’t accept negative voltages on either of the inputs. You can use the previous sketch for the same results – and the resulting voltage will be the value of Vin- subtracted from Vin+. For example, if you had 2 V on Vin+ and 1 V on Vin- the resulting voltage would be 1 V (with the gain set to 1).

Conclusion

Once again I hope you found this of interest, and possibly useful. And if you enjoy my tutorials, or want to introduce someone else to the interesting world of Arduino – check out my new book “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Tutorial – Arduino and the TI ADS1110 16-bit ADC appeared first on tronixstuff.

Tronixstuff 02 Jul 09:06

Tutorial – Arduino and PCF8591 ADC DAC IC

Learn how to use the NXP PCF 8591 8-bit A/D and D/A IC with Arduino in chapter fifty-two of my Arduino Tutorials. The first chapter is here, the complete series is detailed here.

Updated 17/06/2013

Introduction

Have you ever wanted more analogue input pins on your Arduino project, but not wanted to fork out for a Mega? Or would you like to generate analogue signals? Then check out the subject of our tutorial – the NXP PCF8591 IC. It solves both these problems as it has a single DAC (digital to analogue) converter as well as four ADCs (analogue to digital converters) – all accessible via the I2C bus. If the I2C bus is new to you, please familiarise yourself with the readings here before moving forward.

The PCF8591 is available in DIP form, which makes it easy to experiment with:

You can get them from the usual retailers. Before moving on, download the data sheet. The PCF8591 can operate on both 5V and 3.3V so if you’re using an Arduino Due, Raspberry Pi or other 3.3 V development board you’re fine. Now we’ll first explain the DAC, then the ADCs.

Using the DAC (digital-to-analogue converter)

The DAC on the PCF8591 has a resolution of 8-bits – so it can generate a theoretical signal of between zero volts and the reference voltage (Vref) in 255 steps. For demonstration purposes we’ll use a Vref of 5V, and you can use a lower Vref such as 3.3V or whatever you wish the maximum value to be … however it must be less than the supply voltage. Note that when there is a load on the analogue output (a real-world situation), the maximum output voltage will drop – the data sheet (which you downloaded) shows a 10% drop for a 10kΩ load. Now for our demonstration circuit:

Note the use of 10kΩ pull-up resistors on the I2C bus, and the 10μF capacitor between 5V and GND. The I2C bus address is set by a combination of pins A0~A2, and with them all to GND the address is 0x90. The analogue output can be taken from pin 15 (and there’s a seperate analogue GND on pin 13. Also, connect pin 13 to GND, and circuit GND to Arduino GND.

To control the DAC we need to send two bytes of data. The first is the control byte, which simply activates the DAC and is 1000000 (or 0x40) and the next byte is the value between 0 and 255 (the output level). This is demonstrated in the following sketch:

// Example 52.1 PCF8591 DAC demo
// http://tronixstuff.com/tutorials Chapter 52
// John Boxall June 2013
#include "Wire.h"
#define PCF8591 (0x90 >> 1) // I2C bus address
void setup()
{
 Wire.begin();
}
void loop()
{
 for (int i=0; i<256; i++)
 {
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x40); // control byte - turn on DAC (binary 1000000)
 Wire.write(i); // value to send to DAC
 Wire.endTransmission(); // end tranmission
 }

 for (int i=255; i>=0; --i)
 {
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x40); // control byte - turn on DAC (binary 1000000)
 Wire.write(i); // value to send to DAC
 Wire.endTransmission(); // end tranmission
 }
}

Did you notice the bit shift of the bus address in the #define statement? Arduino sends 7-bit addresses but the PCF8591 wants an 8-bit, so we shift the byte over by one bit. 

The results of the sketch are shown below, we’ve connected the Vref to 5V and the oscilloscope probe and GND to the analogue output and GND respectively:

If you like curves you can generate sine waves with the sketch below. It uses a lookup table in an array which contains the necessary pre-calculated data points:

// Example 52.2 PCF8591 DAC demo - sine wave
// http://tronixstuff.com/tutorials Chapter 52
// John Boxall June 2013

#include "Wire.h"
#define PCF8591 (0x90 >> 1) // I2C bus address

uint8_t sine_wave[256] = {
 0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96,
 0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE,
 0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4,
 0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD5, 0xD8,
 0xDA, 0xDC, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE8,
 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4,
 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC,
 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD,
 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6,
 0xF5, 0xF4, 0xF3, 0xF1, 0xF0, 0xEF, 0xED, 0xEB,
 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC,
 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9,
 0xC7, 0xC4, 0xC1, 0xBF, 0xBC, 0xB9, 0xB6, 0xB3,
 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C,
 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83,
 0x80, 0x7D, 0x7A, 0x77, 0x74, 0x70, 0x6D, 0x6A,
 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52,
 0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x3C,
 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28,
 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18,
 0x16, 0x15, 0x13, 0x11, 0x10, 0x0F, 0x0D, 0x0C,
 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04,
 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03,
 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A,
 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15,
 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24,
 0x26, 0x28, 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37,
 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D,
 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64,
 0x67, 0x6A, 0x6D, 0x70, 0x74, 0x77, 0x7A, 0x7D
};
void setup()
{
 Wire.begin();
}
void loop()
{
 for (int i=0; i<256; i++)
 {
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x40); // control byte - turn on DAC (binary 1000000)
 Wire.write(sine_wave[i]); // value to send to DAC
 Wire.endTransmission(); // end tranmission
 }
}

And the results:

For the following DSO image dump, we changed the Vref to 3.3V – note the change in the maxima on the sine wave:

Now you can experiment with the DAC to make sound effects, signals or control other analogue circuits.

Using the ADCs (analogue-to-digital converters)

If you’ve used the analogRead() function on your Arduino (way back in Chapter One) then you’re already familiar with an ADC. With out PCF8591 we can read a voltage between zero and the Vref and it will return a value of between zero and 255 which is directly proportional to zero and the Vref. For example, measuring 3.3V should return 168. The resolution (8-bit) of the ADC is lower than the onboard Arduino (10-bit) however the PCF8591 can do something the Arduino’s ADC cannot. But we’ll get to that in a moment.

First, to simply read the values of each ADC pin we send a control byte to tell the PCF8591 which ADC we want to read. For ADCs zero to three the control byte is 0x00, 0x01, ox02 and 0x03 respectively. Then we ask for two bytes of data back from the ADC, and store the second byte for use. Why two bytes? The PCF8591 returns the previously measured value first – then the current byte. (See Figure 8 in the data sheet). Finally, if you’re not using all the ADC pins, connect the unused ones to GND.

The following example sketch simply retrieves values from each ADC pin one at a time, then displays them in the serial monitor:

// Example 52.3 PCF8591 ADC demo
// http://tronixstuff.com/tutorials Chapter 52
// John Boxall June 2013
#include "Wire.h"
#define PCF8591 (0x90 >> 1) // I2C bus address
#define ADC0 0x00 // control bytes for reading individual ADCs
#define ADC1 0x01
#define ADC2 0x02
#define ADC3 0x03
byte value0, value1, value2, value3;
void setup()
{
 Wire.begin();
 Serial.begin(9600);
}
void loop()
{
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(ADC0); // control byte - read ADC0
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 2);
 value0=Wire.read();
 value0=Wire.read();
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(ADC1); // control byte - read ADC1
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 2);
 value1=Wire.read();
 value1=Wire.read();
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(ADC2); // control byte - read ADC2
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 2);
 value2=Wire.read();
 value2=Wire.read();
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(ADC3); // control byte - read ADC3
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 2);
 value3=Wire.read();
 value3=Wire.read();
 Serial.print(value0); Serial.print(" ");
 Serial.print(value1); Serial.print(" ");
 Serial.print(value2); Serial.print(" ");
 Serial.print(value3); Serial.print(" ");
 Serial.println();
}

Upon running the sketch you’ll be presented with the values of each ADC in the serial monitor. Although it was a simple demonstration to show you how to individually read each ADC, it is a cumbersome method of getting more than one byte at a time from a particular ADC.

To do this, change the control byte to request auto-increment, which is done by setting bit 2 of the control byte to 1. So to start from ADC0 we use a new control byte of binary 00000100 or hexadecimal 0x04. Then request five bytes of data (once again we ignore the first byte) which will cause the PCF8591 to return all values in one chain of bytes. This process is demonstrated in the following sketch:

// Example 52.4 PCF8591 ADC demo
// http://tronixstuff.com/tutorials Chapter 52
// John Boxall June 2013
#include "Wire.h"
#define PCF8591 (0x90 >> 1) // I2C bus address
byte value0, value1, value2, value3;
void setup()
{
 Wire.begin();
 Serial.begin(9600);
}
void loop()
{
 Wire.beginTransmission(PCF8591); // wake up PCF8591
 Wire.write(0x04); // control byte - read ADC0 then auto-increment
 Wire.endTransmission(); // end tranmission
 Wire.requestFrom(PCF8591, 5);
 value0=Wire.read();
 value0=Wire.read();
 value1=Wire.read();
 value2=Wire.read();
 value3=Wire.read();
 Serial.print(value0); Serial.print(" ");
 Serial.print(value1); Serial.print(" ");
 Serial.print(value2); Serial.print(" ");
 Serial.print(value3); Serial.print(" ");
 Serial.println();
}

Previously we mentioned that the PCF8591 can do something that the Arduino’s ADC cannot, and this is offer a differential ADC. As opposed to the Arduino’s single-ended (i.e. it returns the difference between the positive signal voltage and GND, the differential ADC accepts two signals (that don’t necessarily have to be referenced to ground), and returns the difference between the two signals. This can be convenient for measuring small changes in voltages for load cells and so on.

Setting up the PCF8591 for differential ADC is a simple matter of changing the control byte. If you turn to page seven of the data sheet, then consider the different types of analogue input programming. Previously we used mode ’00’ for four inputs, however you can select the others which are clearly illustrated, for example:

So to set the control byte for two differential inputs, use binary 00110000 or 0x30. Then it’s a simple matter of requesting the bytes of data and working with them. As you can see there’s also combination single/differential and a complex three-differential input. However we’ll leave them for the time being.

Conclusion

Hopefully you found this of interest, whether adding a DAC to your experiments or learning a bit more about ADCs. We’ll have some more analogue to digital articles coming up soon, so stay tuned. And if you enjoy my tutorials, or want to introduce someone else to the interesting world of Arduino – check out my new book “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Tutorial – Arduino and PCF8591 ADC DAC IC appeared first on tronixstuff.

Tutorial – Arduino and MC14489 LED Display Driver

Learn how to use MC14489 LED display driver ICs with Arduino in chapter fifty-one of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Updated 12/05/2013

Introduction

Recently we’ve been looking at alternatives to the MAX7219 LED display driver IC due to pricing and availability issues (stay tuned for that one) – and came across an old but still quite useful IC – the MC14489 from Motorola (now Freescale Semiconductor). The MC14489 can drive five seven-segment LED numbers with decimal point, or a combination of numbers and separate LEDs. You can also daisy-chain more than one to drive more digits, and it’s controlled with a simple serial data-clock method in the same way as a 74HC595 shift register. Sourcing the MC14489 isn’t too difficult – it’s available from element14, Newark, Digikey, and so on – or if you’re not in a hurry, try the usual suspects like Futurlec.

For the purpose of the tutorial we’ll show you how to send commands easily from your Arduino or compatible board to control a five-digit 7-segment LED display module – and the instructions are quite simple so they should translate easily to other platforms. Once you have mastered the single module, using more than one MC14489 will be just as easy. So let’s get started.

Hardware

Before moving forward, download the data sheet (pdf). You will need to refer to this as you build the circuit(s). And here’s our subject in real life:

For our demonstration display we’ll be using a vintage HP 5082-7415 LED display module. However you can use almost any 7-segment modules as long as they’re common-cathode – for example, Sparkfun part number COM-11405. If you’re using a four-digit module and want an extra digit, you can add another single digit display. If you want a ruler, the design files are here.

Connecting the MC14489 to an LED display isn’t complex at all. From the data sheet consider Figure 9:

Each of the anode control pins from the MC14489 connect to the matching anodes on your display module, and the BANK1~5 pins connect to the matching digit cathode pins on the display module. You can find the MC14489 pin assignments on page 1 of the data sheet. Seeing as this is chapter fifty-one  – by now you should be confident with finding such information on the data sheets, so I will be encouraging you to do a little more of the work.

Interesting point – you don’t need current-limiting resistors. However you do need the resistor Rx – this controls the current flow to each LED segment. But which value to use? You need to find out the forward current of your LED display (for example 20 mA) then check Figure 7 on page 7 of the data sheet:

To be conservative I’m using a value of 2k0 for Rx, however you can choose your own based on the data sheet for your display and the graph above.  Next – connect the data, clock and enable pins of the MC14489 to three Arduino digital pints – for our example we’re using 5, 6 and 7 for data, clock and enable respectively. Then it’s just 5V and GND to Arduino 5V and GND – and put a 0.1uF capacitor between 5V and GND. Before moving on double-check the connections – especially between the MC14489 and the LED display.

Controlling the MC14489

To control the display we need to send data to two registers in the MC14489 – the configuration register  (one byte) and the display register (three bytes). See page 9 of the data sheet for the overview. The MC14489 will understand that if we send out one byte of data it is to send it the configuration register, and if it receives three bytes of data to send it to the display register. To keep things simple we’ll only worry about the first bit (C0) in the configuration register – this turns the display outputs on or off. To do this, use the following:

digitalWrite(enable, LOW);
shiftOut(data, clock, MSBFIRST, B00000001); // used binary for clarity, however you can use decimal or hexadecimal numbers
digitalWrite(enable, HIGH);
delay(10);

and to turn it off, send bit C0 as zero. The small delay is necessary after each command.

Once you have turned the display on – the next step is to send three bytes of data which represent the numbers to display and decimal points if necessary. Review the table on page 8 of the data sheet. See how they have the binary nibble values for the digits in the third column. Thankfully the nibble for each digit is the binary value for that digit. Furthermore you might want to set the decimal point – that is set using three bits in the first nibble of the three bytes (go back to page 9 and see the display register). Finally you can halve the brightness by setting the very first bit to zero (or one for full brightness).

As an example for that – if you want to display 5.4321 the three bytes of data to send in binary will be:

1101 0101 0100 0011 0010 0001

Let’s break that down. The first bit is 1 for full brightness, then the next three bits (101) turn on the decimal point for BANK5 (the left-most digit). Then you have five nibbles of data, one for each of the digits from left to right. So there’s binary for 5, then four, then three, then two, then one.

digitalWrite(enable, LOW); 
shiftOut(data, clock, MSBFIRST, B11010101); // D23~D16 
shiftOut(data, clock, MSBFIRST, B01000011); // D15~D8
shiftOut(data, clock, MSBFIRST, B00100001); // D7~D0
digitalWrite(enable, HIGH);
delay(10);

To demonstrate everything described so far, it’s been neatly packaged into our first example sketch:

// Example 51.1
// Motorola MC14489 with HP 5082-7415 5-digit, 7-segment LED display
// 2k0 resistor on MC14489 Rx pin
// John Boxall 2013 CC by-sa-nc
// define pins for data from Arduino to MC14489
// we treat it just like a 74HC595
int data = 5;
int clock = 6;
int enable = 7;
void setup()
{
 pinMode(data, OUTPUT);
 pinMode(enable, OUTPUT);
 pinMode(clock, OUTPUT);
 displayOn(); // display defaults to off at power-up
}
void displayTest1()
// displays 5.4321
{
 digitalWrite(enable, LOW); // send 3 bytes to display register. See data sheet page 9
 // you can also insert decimal or hexadecimal numbers in place of the binary numbers
 // we're using binary as you can easily match the nibbles (4-bits) against the table
 // in data sheet page 8
 shiftOut(data, clock, MSBFIRST, B11010101); // D23~D16
 shiftOut(data, clock, MSBFIRST, B01000011); // D15~D8
 shiftOut(data, clock, MSBFIRST, B00100001); // D7~D0
 digitalWrite(enable, HIGH);
 delay(10);
}
void displayTest2()
// displays ABCDE
{
 digitalWrite(enable, LOW); // send 3 bytes to display register. See data sheet page 9
 // you can also insert decimal or hexadecimal numbers in place of the binary numbers
 // we're using binary as you can easily match the nibbles (4-bits) against the table
 // in data sheet page 8
 shiftOut(data, clock, MSBFIRST, B10001010); // D23~D16
 shiftOut(data, clock, MSBFIRST, B10111100); // D15~D8
 shiftOut(data, clock, MSBFIRST, B11011110); // D7~D0
 digitalWrite(enable, HIGH);
 delay(10);
}
void displayOn()
// turns on display
{
 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, B00000001);
 digitalWrite(enable, HIGH);
 delay(10);
}
void displayOff()
// turns off display
{
 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, B00000000);
 digitalWrite(enable, HIGH);
 delay(10);
}
void loop()
{
 displayOn();
 displayTest1();
 delay(1000);
 displayTest2();
 delay(1000);
 displayOff();
 delay(500);
}

… with the results in the following video:


Now that we can display numbers and a few letters with binary, life would be easier if there was a way to take a number and just send it to the display.

So consider the following function that takes an integer between 0 and 99999, does the work and sends it to the display:

void displayIntLong(long x)
// takes a long between 0~99999 and sends it to the MC14489
{
 int numbers[5];
 byte a=0; 
 byte b=0; 
 byte c=0; // will hold the three bytes to send to the MC14489 

 // first split the incoming long into five separate digits
 numbers[0] = int ( x / 10000 ); // left-most digit (will be BANK5)
 x = x % 10000; 
 numbers[1] = int ( x / 1000 );
 x = x % 1000; 
 numbers[2] = int ( x / 100 );
 x = x % 100; 
 numbers[3] = int ( x / 10 );
 x = x % 10; 
 numbers[4] = x % 10; // right-most digit (will be BANK1)

 // now to create the three bytes to send to the MC14489
 // build byte c which holds digits 4 and 5
 c = numbers[3];
 c = c << 4; // move the nibble to the left
 c = c | numbers[4];
 // build byte b which holds digits 3 and 4
 b = numbers [1];
 b = b << 4;
 b = b | numbers[2];
 // build byte a which holds the brightness bit, decimal points and digit 1
 a = B10000000 | numbers[0]; // full brightness, no decimal points

 // now send the bytes to the MC14489
 digitalWrite(enable, LOW);
 shiftOut(data, clock, MSBFIRST, a);
 shiftOut(data, clock, MSBFIRST, b);
 shiftOut(data, clock, MSBFIRST, c); 
 digitalWrite(enable, HIGH);
 delay(10); 
}

So how does that work? First it splits the 5-digit number into separate digits and stores them in the array numbers[]. It then places the fourth digit into a byte, then moves the data four bits to the left – then we bitwise OR the fifth digit into the same byte. This leaves us with a byte of data containing the nibbles for the fourth and fifth digit. The process is repeated for digits 2 and 3. Finally the brightness bit and decimal point bits are assigned to another byte which then has the first digit’s nibble OR’d into it. Which leaves us with bytes a, b and c ready to send to the MC14489. Note that there isn’t any error-checking – however you could add a test to check that the number to be displayed was within the parameter, and if not either switch off the display (see example 51.1) or throw up all the decimal points or … whatever you want.

You can download the demonstration sketch for the function – Example 51.2, and view the results in the following video:

You can also display the letters A to F by sending the values 10 to 15 respectivel to each digit’s nibble. However that would be part of a larger application, which you can (hopefully) by now work out for yourself. Furthermore there’s some other characters that can be displayed – however trying to display the alphabet using 7-segment displays is somewhat passé. Instead, get some 16-segment LED modules or an LCD.

Finally, you can cascade more than one MC14489 to control more digits. Just run a connection from the data out pin on the first MC14889 to the data pin of the second one, and all the clock and enable lines together. Then send out more data – see page 11 of the data sheet. If you’re going to do that in volume other ICs may be a cheaper option and thus lead you back to the MAX7219.

Conclusion

For a chance find the MC14489 is a fun an inexpensive way to drive those LED digit displays. We haven’t covered every single possible option or feature of the part – however you will now have the core knowledge to go further with the MC14489 if you need to move further with it. And if you enjoy my tutorials, or want to introduce someone else to the interesting world of Arduino – check out my new book “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Tutorial – Arduino and MC14489 LED Display Driver appeared first on tronixstuff.

Book – “Arduino Workshop – A Hands-On Introduction with 65 Projects”

Over the last few years I’ve been writing a few Arduino tutorials, and during this time many people have mentioned that I should write a book. And now thanks to the team from No Starch Press this recommendation has morphed into my new book – “Arduino Workshop“:

Although there are seemingly endless Arduino tutorials and articles on the Internet, Arduino Workshop offers a nicely edited and curated path for the beginner to learn from and have fun. It’s a hands-on introduction to Arduino with 65 projects – from simple LED use right through to RFID, Internet connection, working with cellular communications, and much more.

Each project is explained in detail, explaining how the hardware an Arduino code works together. The reader doesn’t need any expensive tools or workspaces, and all the parts used are available from almost any electronics retailer. Furthermore all of the projects can be finished without soldering, so it’s safe for readers of all ages.

The editing team and myself have worked hard to make the book perfect for those without any electronics or Arduino experience at all, and it makes a great gift for someone to get them started. After working through the 65 projects the reader will have gained enough knowledge and confidence to create many things – and to continue researching on their own. Or if you’ve been enjoying the results of my thousands of hours of work here at tronixstuff, you can show your appreciation by ordering a copy for yourself or as a gift

You can review the table of contents, index and download a sample chapter from the Arduino Workshop website.

Arduino Workshop is available from No Starch Press in printed or ebook (PDF, Mobi, and ePub) formats. Ebooks are also included with the printed orders so you can get started immediately.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Book – “Arduino Workshop – A Hands-On Introduction with 65 Projects” appeared first on tronixstuff.

Tutorial – Arduino and ILI9325 colour TFT LCD modules

Learn how to use inexpensive ILI9325 colour TFT LCD modules in chapter fifty of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Introduction

Colour TFT LCD modules just keep getting cheaper, so in this tutorial we’ll show you how to get going with some of the most inexpensive modules we could find. The subject of our tutorial is a 2.8″ 240 x 320 TFT module with the ILI9325 LCD controller chip. If you look in ebay this example should appear pretty easily, here’s a photo of the front and back to help identify it:

There is also the line “HY-TFT240_262k HEYAODZ110510” printed on the back of the module. They should cost less than US$10 plus shipping. Build quality may not be job number one at the factory so order a few, however considering the cost of something similar from other retailers it’s cheap insurance. You’ll also want sixteen male to female jumper wires to connect the module to your Arduino.

Getting started

To make life easier we’ll use an Arduino library “UTFT” written for this and other LCD modules. It has been created by Henning Karlsen and can be downloaded from his website. If you can, send him a donation – this library is well worth it. Once you’ve downloaded and installed the UTFT library, the next step is to wire up the LCD for a test.

Run a jumper from the following LCD module pins to your Arduino Uno (or compatible):

  • DB0 to DB7 > Arduino D0 to D7 respectively
  • RD > 3.3 V
  • RSET > A2
  • CS > A3
  • RW > A4
  • RS > A5
  • backlight 5V > 5V
  • backlight GND > GND

Then upload the following sketch – Example 50.1. You should be presented with the following on your display:

If you’re curious, the LCD module and my Eleven board draws 225 mA of current. If that didn’t work for you, double-check the wiring against the list provided earlier. Now we’ll move forward and learn how to display text and graphics.

Sketch preparation

You will always need the following before void setup():

#include "UTFT.h"
UTFT myGLCD(ILI9325C,19,18,17,16); // for Arduino Uno

and in void setup():

myGLCD.InitLCD(orientation); 
myGLCD.clrScr();

with the former command, change orientation to either LANDSCAPE to PORTRAIT depending on how you’ll view the screen. You may need further commands however these are specific to features that will be described below. The function .clrScr() will clear the screen.

Displaying Text

There are three different fonts available with the library. To use them add the following three lines before void setup():

extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

When displaying text you’ll need to define the foreground and background colours with the following:

myGLCD.setColor(red, green, blue); 
myGLCD.setBackColor(red, green, blue);

Where red, green and blue are values between zero and 255. So if you want white use 255,255,255 etc. For some named colours and their RGB values, click here. To select the required font, use one of the following:

myGLCD.setFont(SmallFont); // Allows 20 rows of 40 characters
myGLCD.setFont(BigFont); // Allows 15 rows of 20 characters
myGLCD.setFont(SevenSegNumFont); // allows display of 0 to 9 over four rows

Now to display the text use the function:

myGLCD.print("text to display",x, y);

where text is what you’d like to display, x is the horizontal alignment (LEFT, CENTER, RIGHT) or position in pixels from the left-hand side of the screen and y is the starting point of the top-left of the text. For example, to start at the top-left of the display y would be zero. You can also display a string variable instead of text in inverted commas.

You can see all this in action with the following sketch – Example 50.2, which is demonstrated in the following video:

Furthremore, you can also specify the angle of display, which gives a simple way of displaying text on different slopes. Simply add the angle as an extra parameter at the end:

myGLCD.print("Hello, world", 20, 20, angle);

Again, see the following sketch – Example 50.2a, and the results below:

Displaying Numbers

Although you can display numbers with the text functions explained previously, there are two functions specifically for displaying integers and floats.

You can see these functions in action with the following sketch – Example 50.3, with an example of the results below:

Displaying Graphics

There’s a few graphic functions that can be used to create required images. The first is:.

myGLCD.fillScr(red, green, blue);

which is used the fill the screen with a certain colour. The next simply draws a pixel at a specified x,y location:

myGLCD.drawPixel(x,y);

Remember that the top-left of the screen is 0,0. Moving on, to draw a single line, use:

myGLCD.drawLine(x1,0,x2,239);

where the line starts at x1,y1 and finishes at x2,y2. Need a rectangle? Use:

myGLCD.drawRect(x1,y2,x2,y2); // for open rectangles
myGLCD.fillRect(x1,y2,x2,y2); // for filled rectangles

where the top-left of the rectangle is x1,y1 and the bottom-right is x2, y2. You can also have rectangles with rounded corners, just use:

myGLCD.drawRoundRect(x1,y2,x2,y2); // for open rectangles
myGLCD.fillRoundRect(x1,y2,x2,y2); // for filled rectangles

instead. And finally, circles – which are quite easy. Just use:

myGLCD.drawCircle(x,y,r); // draws open circle
myGLCD.fillCircle(x,y,r); // draws a filled circle

where x,y are the coordinates for the centre of the circle, and r is the radius. For a quick demonstration of all the graphic functions mentioned so far, see Example 50.4 – and the following video:

Displaying bitmap images

If you already have an image in .gif, .jpg or .png format that’s less than 300 KB in size, this can be displayed on the LCD. To do so, the file needs to be converted to an array which is inserted into your sketch. Let’s work with a simple example to explain the process. Below is our example image:

Save the image of the puppy somewhere convenient, then visit this page. Select the downloaded file, and select the .c and Arduino radio buttons, then click “make file”. After a moment or two a new file will start downloading. When it arrives, open it with a text editor – you’ll see it contains a huge array and another #include statement – for example:

Past the #include statement and the array into your sketch above void setup(). After doing that, don’t be tempted to “autoformat” the sketch in the Arduino IDE. Now you can use the following function to display the bitmap on the LCD:

myGLCD.drawBitmap(x,y,width,height, name, scale);

Where x and y are the top-left coordinates of the image, width and height are the … width and height of the image, and name is the name of the array. Scale is optional – you can double the size of the image with this parameter. For example a value of two will double the size, three triples it – etc. The function uses simple interpolation to enlarge the image, and can be a clever way of displaying larger images without using extra memory. Finally, you can also display the bitmap on an angle – using:

myGLCD.drawBitmap(x,y,width,height, name, angle, cx, cy);

where angle is the angle of rotation and cx/cy are the coordinates for the rotational centre of the image.

The bitmap functions using the example image have been used in the following sketch – Example 50.5, with the results in the following video:

Unfortunately the camera doesn’t really do the screen justice, it looks much better with the naked eye.

What about the SD card socket and touch screen?

The SD socket didn’t work, and I won’t be working with the touch screen at this time.

Conclusion

So there you have it – an incredibly inexpensive and possibly useful LCD module. Thank you to Henning Karlsen for his useful library, and if you found it useful – send him a donation via his page.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Tutorial – Arduino and ILI9325 colour TFT LCD modules appeared first on tronixstuff.

Tronixstuff 26 Apr 02:31

Arduino and KTM-S1201 LCD modules

Learn how to use very inexpensive KTM-S1201 LCD modules in this edition of our Arduino tutorials. This is chapter forty-nine of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Introduction

After looking for some displays to use with another (!) clock, I came across some 12-digit numeric LCD displays. They aren’t anything flash, and don’t have a back light –  however they were one dollar each. How could you say no to that? So I ordered a dozen to try out. The purpose of this tutorial is to show you how they are used with an Arduino in the simplest manner possible.

Moving forward – the modules look like OEM modules for desktop office phones from the 1990s:

With a quick search on the Internet you will find a few sellers offering them for a dollar each. The modules (data sheet) use the NEC PD7225 controller IC (data sheet):

They aren’t difficult to use, so I’ll run through set up and operation with a few examples.

Hardware setup

First you’ll need to solder some sort of connection to the module – such as 2×5 header pins. This makes it easy to wire it up to a breadboard or a ribbon cable:

The rest of the circuitry is straight-forward. There are ten pins in two rows of five, and with the display horizontal and the pins on the right, they are numbered as such:

Now make the following connections:

  • LCD pin 1 to 5V
  • LCD pin 2 to GND
  • LCD pin 3 to Arduino D4
  • LCD pin 4 to Arduino D5
  • LCD pin 5 to Arduino D6
  • LCD pin 6 to Arduino D7
  • LCD pin 7 – not connected
  • LCD pin 8 – Arduino D8
  • LCD pin 9 to the centre pin of a 10k trimpot – whose other legs connect to 5V and GND. This is used to adjust the contrast of the LCD.

The Arduino digital pins that are used can be changed – they are defined in the header file (see further on). If you were curious as to how low-current these modules are:

That’s 0.689 mA- not bad at all. Great for battery-powered operations. Now that you’ve got the module wired up, let’s get going with some demonstration sketches.

Software setup

The sketches used in this tutorial are based on work by Jeff Albertson and Robert Mech, so kudos to them – however we’ve simplified them a little to make use easier. We’ll just cover the functions required to display data on the LCD. However feel free to review the sketches and files along with the controller chip datasheet as you’ll get an idea of how the controller is driven by the Arduino.

When using the LCD module you’ll need a header file in the same folder as your sketch. You can download the header file from here. Then every time you open a sketch that uses the header file, it should appear in a tab next to the main sketch, for example:

There’s also a group of functions and lines required in your sketch. We’ll run through those now – so download the first example sketch, add the header file and upload it. Your results should be the same as the video below:

So how did that work? Take a look at the sketch you uploaded.  You need all the functions between the two lines of “////////////////////////” and also the five lines in void setup(). Then you can display a string of text or numbers using

ktmWriteString();

which was used in void loop(). You can use the digits 0~9, the alphabet (well, what you can do with 7-segments), the degrees symbol (use an asterix – “*”) and a dash (use  – “-“). So if your sketch can put together the data to display in a string, then that’s taken care of.

If you want to clear the screen, use:

ktmCommand(_ClearDsp);

Next – to individually place digits on the screen, use the function:

tmPrnNumb(n,p,d,l);

Where n is the number to be displayed (zero or a positive integer), p is the position on the LCD for the number’s  (the positions from left to right are 11 to 0…), d is the number of digits to the right of the decimal point (leave as zero if you don’t want a decimal point), and l is the number of digits being displayed for n. When you display digits using this function you can use more than one function to compose the number to be displayed – as this function doesn’t clear the screen.

To help get your head around it, the following example sketch (download) has a variety of examples in void loop(). You can watch this example in the following video:

Conclusion

So there you have it – an incredibly inexpensive and possibly useful LCD module. Thank you to Jeff Albertson and Robert Mech for their help and original code.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Arduino and KTM-S1201 LCD modules appeared first on tronixstuff.

Exploring the TI Stellaris platform with Energia Arduino-compatible IDE

Introduction

In the same manner as their MSP430 development board, Texas Instruments also have another LaunchPad board with their powerful Stellaris LM4F120H5QR microcontroller. It’s an incredibly powerful and well-featured MCU – which offers an 80 MHz, 32-bit ARM Cortex-M4 CPU with floating point, 256 Kbytes of 100,000 write-erase cycle FLASH and many peripherals such as 1MSPS ADCs, eight UARTs, four SPIs, four I2Cs, USB & up to 27 timers, some configurable up to 64-bits.

That’s a bucket of power, memory and I/O for not much money – you can get the LaunchPad board for around $15. This LaunchPad has the in-circuit debugger, two user buttons, an RGB LED and connectors for I/O and shield-like booster packs:

and the other side:

However the good news as far as we’re concerned is that you can now use it with the Energia Arduino-compatible IDE that we examined previously. Before rushing out to order your own Stellaris board, install Energia and examine the available functions and libraries to make sure you can run what you need. And if so, you’re set for some cheap Arduino power.

Installation

Installation is simple, just get your download from here. If you’re running Windows 7 – get the USB drivers from here. When you plug your LaunchPad into the USB for the first time, wait until after Windows attempts to install the drivers, then install drivers manually after download via Device manager … three times (JTAG, virtual serial port and DFU device). Use the debug USB socket (and set the switch to debug) when installing and uploading code. If you get the following warning from Windows, just click “Install this driver software anyway”:

Once the drivers are installed, plug in your LaunchPad, wait a moment – then run Energia. You can then select your board type and serial port just like the Arduino IDE. Then go ahead and upload the “blink” example…

Awesome – check out all that free memory space. In the same manner as the MSP430, there are some hardware<>sketch differences you need to be aware of. For example, how to refer to the I/O pins in Energia? A map has been provided for front:

… and back:

As you can imagine, the Stellaris MCUs are different to an AVR, so a lot of hardware-specific code doesn’t port over from the world of Arduino. One of the first things to remember is that the Stellaris is a 3.3V device. Code may or may not be interchangeable, so a little research will be needed to match up the I/O pins and rewrite the sketch accordingly. For example, instead of digital pins numbers, you use PX_Y – see the map above. So let’s say you want to run through the RGB LED… consider the following sketch:

int wait = 500;
void setup() 
{ 
 // initialize the digital pin as an output.
 pinMode(PF_1, OUTPUT); // red 
 pinMode(PF_3, OUTPUT); // green
 pinMode(PF_2, OUTPUT); // blue
}
void loop() 
{
 digitalWrite(PF_1, HIGH); 
 delay(wait); 
 digitalWrite(PF_1, LOW); 
 digitalWrite(PF_3, HIGH); 
 delay(wait); 
 digitalWrite(PF_3, LOW); 
 digitalWrite(PF_2, HIGH); 
 delay(wait); 
 digitalWrite(PF_2, LOW); 
}

Which simply blinks the red, green and blue LED elements in series. Using digital inputs is in the same vein, and again the buttons are wired so when pressed they go LOW. An example of this in the following sketch:

void setup() 
{ 
 // initialize the digital pins
 pinMode(PF_1, OUTPUT); // red 
 pinMode(PF_3, OUTPUT); // green
 pinMode(PF_2, OUTPUT); // blue

 pinMode(PF_4, INPUT_PULLUP); // left - note _PULLUP
 pinMode(PF_0, INPUT_PULLUP); // right - note _PULLUP 
}
void blinkfast() 
{
 for (int i=0; i<10; i++)
 {
 digitalWrite(PF_1, HIGH); 
 delay(250); 
 digitalWrite(PF_1, LOW); 
 digitalWrite(PF_3, HIGH); 
 delay(250); 
 digitalWrite(PF_3, LOW); 
 digitalWrite(PF_2, HIGH); 
 delay(250); 
 digitalWrite(PF_2, LOW); 
 }
}
void blinkslow() 
{
 for (int i=0; i<5; i++)
 {
 digitalWrite(PF_1, HIGH); 
 delay(1000); 
 digitalWrite(PF_1, LOW); 
 digitalWrite(PF_3, HIGH); 
 delay(1000); 
 digitalWrite(PF_3, LOW); 
 digitalWrite(PF_2, HIGH); 
 delay(1000); 
 digitalWrite(PF_2, LOW); 
 }
}
void loop()
{
 if (digitalRead(PF_4)==LOW) { blinkslow(); }
 if (digitalRead(PF_0)==LOW) { blinkfast(); }
}

And for the non-believers:

Where to from here? 

Sometimes you can be platform agnostic, and just pick something that does what you want with the minimum of time and budget. Or to put it another way, if you need a fast CPU and plenty of space but couldn’t be bothered don’t have time to work with Keil, Code Composer Studio, IAR etc – the Energia/Stellaris combination could solve your problem. There’s a growing Energia/Stellaris forum, and libraries can be found here. At the time of writing we found an I2C library as well.

However to take full advantage of the board, consider going back to the TI tools and move forward with them. You can go further with the tutorials and CCS etc from Texas Instruments own pages.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column? And join our friendly Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

The post Exploring the TI Stellaris platform with Energia Arduino-compatible IDE appeared first on tronixstuff.

Tutorial: Arduino and the MSGEQ7 Spectrum Analyzer

This is a tutorial on using the MSGEQ7 Spectrum Analyser with Arduino, and chapter forty-eight of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe. The first chapter is here, the complete series is detailed here.

Updated 10/11/2014

In this article we’re going to explain how to make simple spectrum analysers with an Arduino-style board. (Analyser? Analyzer? Take your pick).

First of all, what is a spectrum analyser? Good question. Do you remember what  this is?

It’s a mixed graphic equaliser/spectrum analyser deck for a hi-fi system. The display in the middle is the spectrum analyser, and roughly-speaking it shows the strength of  different frequencies in the music being listened to – and looked pretty awesome doing it. We can recreate displays similar to this for entertainment and also as a base for creative lighting effects. By working through this tutorial you’ll have the base knowledge to recreate these yourself.

We’ll be using the MSGEQ7 “seven band graphic equaliser IC” from Mixed Signal Integration. Here’s the MSGEQ7 data sheet (.pdf).  This little IC can accept a single audio source, analyse seven frequency bands of the audio, and output a DC representation of each frequency band. This isn’t super-accurate or calibrated in any way, but it works. You can get the IC separately, for example:


and then build your own circuit around it… or like most things in the Arduino world – get a shield. In this case, a derivative of the original Bliptronics shield by Sparkfun. It’s designed to pass through stereo audio via 3.5mm audio sockets and contains two MSGEQ7s, so we can do a stereo analyser:

As usual Sparkfun have saved a few cents by not including the stackable header sockets, so you’ll need to buy and solder those in yourself. There is also space for three header pins for direct audio input (left, right and common), which are useful – so if you can add those as well.

So now you have a shield that’s ready for use. Before moving forward let’s examine how the MSGEQ7 works for us. As mentioned earlier, it analyses seven frequency bands. These are illustrated in the following graph from the data sheet:

It will return the strengths of the audio at seven points – 63 Hz, 160 Hz, 400 Hz, 1 kHz, 2.5 kHz, 6.25 kHz and 16 kHz – and as you can see there is some overlap between the bands. The strength is returned as a DC voltage – which we can then simply measure with the Arduino’s analogue input and create a display of some sort. At this point audio purists, Sheldonites and RF people might get a little cranky, so once again – this is more for visual indication than any sort of calibration device.

However as an 8-pin IC a different approach is required to get the different levels. The IC will sequentially give out the levels for each band on pin 3- e.g. 63 Hz then 160 Hz then 400 Hz then 1 kHz then 2.5 kHz then 6.25 kHz  then 16 kHz then back to 63 Hz and so on. To start this sequence we first reset the IC by pulsing the RESET pin HIGH then low. This tells the IC to start at the first band. Next, we set the STROBE pin to LOW, take the DC reading from pin 3 with analogue input, store the value in a variable (an array), then set the STROBE pin HIGH. We repeat the strobe-measure sequence six more times to get the rest of the data, then RESET the IC and start all over again. For the visual learners consider the diagram below from the data sheet:

To demonstrate this process, consider the function

readMSGEQ7()

in the following example sketch:

// Example 48.1 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013 
// MSGEQ7 spectrum analyser shield - basic demonstration
int strobe = 4; // strobe pins on digital 4
int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays
int right[7];
int band;
void setup()
{
 Serial.begin(115200);
 pinMode(res, OUTPUT); // reset
 pinMode(strobe, OUTPUT); // strobe
 digitalWrite(res,LOW); // reset low
 digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield
}
void readMSGEQ7()
// Function to read 7 band equalizers
{
 digitalWrite(res, HIGH);
 digitalWrite(res, LOW);
 for(band=0; band <7; band++)
 {
 digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band 
 delayMicroseconds(30); // 
 left[band] = analogRead(0); // store left band reading
 right[band] = analogRead(1); // ... and the right
 digitalWrite(strobe,HIGH); 
 }
}
void loop()
{
 readMSGEQ7();
 // display values of left channel on serial monitor
 for (band = 0; band < 7; band++)
 {
 Serial.print(left[band]);
 Serial.print(" ");
 }
 Serial.println();
// display values of right channel on serial monitor
 for (band = 0; band < 7; band++)
 {
 Serial.print(right[band]);
 Serial.print(" ");
 }
 Serial.println();
}

If you follow through the sketch, you can see that it reads both left- and right-channel values from the two MSGEQ7s on the shield, then stores each value in the arrays left[] and right[]. These values are then sent to the serial monitor for display – for example:

If you have a function generator, connect the output to one of the channels and GND – then adjust the frequency and amplitude to see how the values change. The following video clip is a short demonstration of this – we set the generator to 1 kHz and adjust the amplitude of the signal. To make things easier to read we only measure and display the left channel:


Keep an eye on the fourth column of data – this is the analogRead() value returned by the Arduino when reading the 1khz frequency band. You can also see the affect on the other bands around 1 kHz as we increase and decrease the frequency. However that wasn’t really visually appealing – so now we’ll create a small and large graphical version.

First we’ll use an inexpensive LCD, the I2C model from akafugu reviewed previously. To save repeating myself, also review how to create custom LCD characters from here.

With the LCD with have two rows of sixteen characters. The plan is to use the top row for the levels, the left-channel’s on … the left, and the right on the right. Each character will be a little bar graph for the level. The bottom row can be for a label. We don’t have too many pixels to work with, but it’s a compact example:

We have eight rows for each character, and the results from an analogueRead() fall between 0 and 1023. So that’s 1024 possible values spread over eight sections. Thus each row of pixels in each character will represent 128 “units of analogue read” or around 0.63 V if the Arduino is running from true 5 V (remember your AREF notes?). The sketch will again read the values from the MSGEQ7, feed them into two arrays – then display the required character in each band space  on the LCD.

Here’s the resulting sketch:

// Example 48.2 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013 
// MSGEQ7 spectrum analyser shield and I2C LCD from akafugu
// for akafugu I2C LCD
#include "Wire.h"
#include "TWILiquidCrystal.h"
LiquidCrystal lcd(50);
// create custom characters for LCD
byte level0[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111};
byte level1[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111};
byte level2[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};
byte level3[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111};
byte level4[8] = { 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte level5[8] = { 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte level6[8] = { 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
byte level7[8] = { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
int strobe = 4; // strobe pins on digital 4
int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays
int right[7];
int band;
void setup()
{
 Serial.begin(9600);
 // setup LCD and custom characters
 lcd.begin(16, 2);
 lcd.setContrast(24);
 lcd.clear();
lcd.createChar(0,level0);
 lcd.createChar(1,level1);
 lcd.createChar(2,level2);
 lcd.createChar(3,level3);
 lcd.createChar(4,level4);
 lcd.createChar(5,level5);
 lcd.createChar(6,level6);
 lcd.createChar(7,level7);
 lcd.setCursor(0,1);
 lcd.print("Left");
 lcd.setCursor(11,1);
 lcd.print("Right");
 pinMode(res, OUTPUT); // reset
 pinMode(strobe, OUTPUT); // strobe
 digitalWrite(res,LOW); // reset low
 digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield
}
void readMSGEQ7()
// Function to read 7 band equalizers
{
 digitalWrite(res, HIGH);
 digitalWrite(res, LOW);
 for( band = 0; band < 7; band++ )
 {
 digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band 
 delayMicroseconds(30); // 
 left[band] = analogRead(0); // store left band reading
 right[band] = analogRead(1); // ... and the right
 digitalWrite(strobe,HIGH); 
 }
}
void loop()
{
 readMSGEQ7();
// display values of left channel on LCD
 for( band = 0; band < 7; band++ )
 {
 lcd.setCursor(band,0);
 if (left[band]>=895) { lcd.write(7); } else
 if (left[band]>=767) { lcd.write(6); } else
 if (left[band]>=639) { lcd.write(5); } else
 if (left[band]>=511) { lcd.write(4); } else
 if (left[band]>=383) { lcd.write(3); } else
 if (left[band]>=255) { lcd.write(2); } else
 if (left[band]>=127) { lcd.write(1); } else
 if (left[band]>=0) { lcd.write(0); }
 }
 // display values of right channel on LCD
 for( band = 0; band < 7; band++ )
 {
 lcd.setCursor(band+9,0);
 if (right[band]>=895) { lcd.write(7); } else
 if (right[band]>=767) { lcd.write(6); } else
 if (right[band]>=639) { lcd.write(5); } else
 if (right[band]>=511) { lcd.write(4); } else
 if (right[band]>=383) { lcd.write(3); } else
 if (right[band]>=255) { lcd.write(2); } else
 if (right[band]>=127) { lcd.write(1); } else
 if (right[band]>=0) { lcd.write(0); }
 }
}

If you’ve been reading through my tutorials there isn’t anything new to worry about. And now for the demo, with sound –

That would look great on the side of a Walkman, however it’s a bit small. Let’s scale it up by using a Freetronics Dot Matrix Display – you may recall these from Clock One. For some background knowledge check the review here.  Don’t forget to use a suitable power supply for the DMD – 5 V at 4 A will do nicely. The DMD contains 16 rows of 32 LEDs. This gives us twice the “resolution” to display each band level if desired. The display style is subjective, so for this example we’ll use a single column of LEDs for each frequency band, with a blank column between each one.

We use a lot of line-drawing statements to display the levels, and clear the DMD after each display. With this and the previous sketches, there could be room for efficiency – however I write these with the beginner in mind. Here’s the sketch:

// Example 48.3 - tronixstuff.com/tutorials > chapter 48 - 30 Jan 2013 
// MSGEQ7 spectrum analyser shield with a Freetronics DMD
// for DMD
#include "DMD.h" // for DMD
#include "SPI.h" // SPI.h must be included as DMD is written by SPI (the IDE complains otherwise)
#include "TimerOne.h"
#include "SystemFont5x7.h" // keep next two lines if you want to add some text
#include "Arial_black_16.h"
DMD dmd(1, 1); // creates instance of DMD to refer to in sketch
void ScanDMD() // necessary interrupt handler for refresh scanning of DMD
{ 
 dmd.scanDisplayBySPI();
}
int strobe = 4; // strobe pins on digital 4
int res = 5; // reset pins on digital 5
int left[7]; // store band values in these arrays
int right[7];
int band;
void setup()
{
 // for DMD
 //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
 Timer1.initialize( 5000 ); //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
 Timer1.attachInterrupt( ScanDMD ); //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI() 
 dmd.clearScreen( true ); //true is normal (all pixels off), false is negative (all pixels on)

 // for MSGEQ7
 pinMode(res, OUTPUT); // reset
 pinMode(strobe, OUTPUT); // strobe
 digitalWrite(res,LOW); // reset low
 digitalWrite(strobe,HIGH); //pin 5 is RESET on the shield
}
void readMSGEQ7()
// Function to read 7 band equalizers
{
 digitalWrite(res, HIGH);
 digitalWrite(res, LOW);
 for( band = 0; band < 7; band++ )
 {
 digitalWrite(strobe,LOW); // strobe pin on the shield - kicks the IC up to the next band 
 delayMicroseconds(30); // 
 left[band] = analogRead(0); // store left band reading
 right[band] = analogRead(1); // ... and the right
 digitalWrite(strobe,HIGH); 
 }
}
void loop()
{
 int xpos;
 readMSGEQ7();
 dmd.clearScreen( true ); 
 // display values of left channel on DMD
 for( band = 0; band < 7; band++ )
 {
 xpos = (band*2)+1;
 if (left[band]>=895) { dmd.drawLine( xpos, 15, xpos, 1, GRAPHICS_NORMAL ); } else
 if (left[band]>=767) { dmd.drawLine( xpos, 15, xpos, 3, GRAPHICS_NORMAL ); } else
 if (left[band]>=639) { dmd.drawLine( xpos, 15, xpos, 5, GRAPHICS_NORMAL ); } else
 if (left[band]>=511) { dmd.drawLine( xpos, 15, xpos, 7, GRAPHICS_NORMAL ); } else
 if (left[band]>=383) { dmd.drawLine( xpos, 15, xpos, 9, GRAPHICS_NORMAL ); } else
 if (left[band]>=255) { dmd.drawLine( xpos, 15, xpos, 11, GRAPHICS_NORMAL ); } else
 if (left[band]>=127) { dmd.drawLine( xpos, 15, xpos, 13, GRAPHICS_NORMAL ); } else
 if (left[band]>=0) { dmd.drawLine( xpos, 15, xpos, 15, GRAPHICS_NORMAL ); }
 }

 // display values of right channel on DMD
 for( band = 0; band < 7; band++ )
 {
 xpos = (band*2)+18;
 if (right[band]>=895) { dmd.drawLine( xpos, 15, xpos, 1, GRAPHICS_NORMAL ); } else
 if (right[band]>=767) { dmd.drawLine( xpos, 15, xpos, 3, GRAPHICS_NORMAL ); } else
 if (right[band]>=639) { dmd.drawLine( xpos, 15, xpos, 5, GRAPHICS_NORMAL ); } else
 if (right[band]>=511) { dmd.drawLine( xpos, 15, xpos, 7, GRAPHICS_NORMAL ); } else
 if (right[band]>=383) { dmd.drawLine( xpos, 15, xpos, 9, GRAPHICS_NORMAL ); } else
 if (right[band]>=255) { dmd.drawLine( xpos, 15, xpos, 11, GRAPHICS_NORMAL ); } else
 if (right[band]>=127) { dmd.drawLine( xpos, 15, xpos, 13, GRAPHICS_NORMAL ); } else
 if (right[band]>=0) { dmd.drawLine( xpos, 15, xpos, 15, GRAPHICS_NORMAL ); }
 }
}

… and here it is in action:

Conclusion

At this point you have the knowledge to use the MSGEQ7 ICs to create some interesting spectrum analysers for entertainment and visual appeal – now you just choose the type of display enjoy the results. And if you enjoyed this article, or want to introduce someone else to the interesting world of Arduino – check out my book (now in a fourth printing!) “Arduino Workshop”.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our forum – dedicated to the projects and related items on this website.

The post Tutorial: Arduino and the MSGEQ7 Spectrum Analyzer appeared first on tronixstuff.