Tag Archive | "NXP"

Use the NXP PCF8563 real-time clock IC with Arduino in chapter fifty-four of our Arduino Tutorials. The first chapter is here, the complete series is detailed here.

Updated 20/08/2013

Introduction

Recently a few people have been asking about the PCF8563 real-time clock IC from NXP – so this is a tutorial on how to use it for time, date, alarm clock and square-wave generation purposes.

The PCF8563 is another inexpensive RTC that can be used with an Arduino or other platforms due to the wide operating voltage (1 to 5.5V DC), I2C interface, and very low power consumption (when powered by a backup battery it only draws 0.25 μA). If you aren’t up to speed on the I2C interface, please review the I2C tutorials before moving forward. And please download the data sheet (.pdf).

The PCF8563 is available in various chip packages, for the curious we’re using the TSSOP8 version mounted on a breakout board:

Don’t panic – you can also get it in a breadboard-friendly DIP (through-hole) package as well, and also on a pre-built module from the usual suspects.

Demonstration Circuit

If you have a pre-made module, you can skip to the next section. However if you’re making up the circuit yourself, you will need:

One 32.768 kHz crystal

Two 1N4148 diodes*

One 3V coin cell (with holder)*

Two 10kΩ resistors

One 0.1 uF capacitor

And here’s the schematic:

* You can skip the diodes and battery if you don’t want a backup power supply when the main power is turned off or removed. Pin 3 is for the interrupt output (we’ll consider that later) and pin 7 is for the square-wave oscillator output.

Communicating with the PCF8563

Now to get down into the land of I2C once more. When looking through the data sheet NXP mentions two bus addresses, which have the same 7-bits finished with either a 1 for read or 0 for write. However you can just bitshift it over one bit as we don’t need the R/W bit – which gives you a bus address of 0x51.

Next you need to know which registers store the time and date – check the register map (table 4) on page 7 of the data sheet:

There will be a few other registers of interest, but we’ll return to those later. For now, note that the time and date start from 0x02. And one more thing – data is stored in the BCD (binary-coded- decimal) format. But don’t panic, we have a couple of functions to convert numbers between BCD and decimal.

Writing the time and date is a simple matter of collating the seconds, minutes, hours, day of week, day of month, month and year into bytes, converting to BCD then sending them to the PCF8563 with seven Wire.write() functions. Reading the data is also easy, just set the pointer to 0x02 and request seven bytes of data – then run them through a BCD to decimal conversion. With a catch.

And that catch is the need to sort out unwanted bits. Revisit table 4 in the data sheet – if you see an x that’s an unused bit. If any of them are a 1 they will mess up the BCD-decimal conversion when reading the register, so they need to be eliminated just like a whack-a-mole. To do this, we perform an & (bitwise AND) operation on the returned byte and mask out the unwanted bits with a zero. How does that work?

Example – the byte for dayOfMonth is returned – we only need bits 5 to 0. So 6 and 7 are superfluous. If you use (dayOfMonth & B00111111) the & function will set bits 6 and 7 to zero, and leave the other bits as they were.

Now to put all that together in a demonstration sketch. It puts everything mentioned to work and simply sets the time to the PCF8563, and then returns it to the serial monitor. The data is kept in global variables declared at the start of the sketch, and the conversions between BCD and decimal are done “on the fly” in the functions used to send or retrieve data from the PCF8563. Read through the following sketch and see how it works for yourself:

month=bcdToDec(Wire.read()&B00011111);// remove century bit, 1999 is over

year=bcdToDec(Wire.read());

}

voidsetup()

{

Wire.begin();

Serial.begin(9600);

// change the following to set your initial time

second=0;

minute=28;

hour=9;

dayOfWeek=2;

dayOfMonth=13;

month=8;

year=13;

// comment out the next line and upload again to set and keep the time from resetting every reset

setPCF8563();

}

voidloop()

{

readPCF8563();

Serial.print(days[dayOfWeek]);

Serial.print(" ");

Serial.print(dayOfMonth,DEC);

Serial.print("/");

Serial.print(month,DEC);

Serial.print("/20");

Serial.print(year,DEC);

Serial.print(" - ");

Serial.print(hour,DEC);

Serial.print(":");

if(minute<10)

{

Serial.print("0");

}

Serial.print(minute,DEC);

Serial.print(":");

if(second<10)

{

Serial.print("0");

}

Serial.println(second,DEC);

delay(1000);

}

And a quick video of this in operation:

If all you need to do is write and read the time with the PCF8563, you’re ready to go. However there’s a few more features of this unassuming little part which you might find useful, so at least keep reading…

Square-wave output

As with any clock or RTC IC, an oscillator is involved, and as mentioned earlier you can take this from pin 7 of the PCF8563. However – it’s an open-drain output – which means current flows from the supply voltage into pin 7. For example if you want to blink an LED, connect a 560Ω resistor between 5V and the anode of the LED, then connect the cathode to pin 7 of the PCF8563.

The frequency is controlled from the register at 0x0D. Simply write one of the following values for the respective frequencies:

10000000 for 32.768 kHz;

10000001 for 1.024 kHz;

10000010 for 32 kHz;

10000011 for 1 Hz;

0 turns the output off and sets it to high impedance.

The following is a quick demonstration sketch which runs through the options:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

// Example 54.2 - PCF8563 square-wave generator (signal from pin 7)

#include "Wire.h"

#define PCF8563address 0x51

voidPCF8563oscOFF()

// turns off oscillator

{

Wire.beginTransmission(PCF8563address);

Wire.write(0x0D);

Wire.write(0);

Wire.endTransmission();

}

voidPCF8563osc1Hz()

// sets oscillator to 1 Hz

{

Wire.beginTransmission(PCF8563address);

Wire.write(0x0D);

Wire.write(B10000011);

Wire.endTransmission();

}

voidPCF8563osc32Hz()

// sets oscillator to 32 kHz

{

Wire.beginTransmission(PCF8563address);

Wire.write(0x0D);

Wire.write(B10000010);

Wire.endTransmission();

}

voidPCF8563osc1024kHz()

// sets oscillator to 1.024 kHz

{

Wire.beginTransmission(PCF8563address);

Wire.write(0x0D);

Wire.write(B10000001);

Wire.endTransmission();

}

voidPCF8563osc32768kHz()

// sets oscillator to 32.768 kHz

{

Wire.beginTransmission(PCF8563address);

Wire.write(0x0D);

Wire.write(B10000000);

Wire.endTransmission();

}

voidsetup()

{

Wire.begin();

}

voidloop()

{

PCF8563osc1Hz();

delay(2000);

PCF8563osc32Hz();

delay(2000);

PCF8563osc1024kHz();

delay(2000);

PCF8563osc32768kHz();

delay(2000);

PCF8563oscOFF();

delay(2000);

}

And the resulting waveforms from slowest to highest frequency. Note the sample was measured from a point between the LED and resistor, so the oscillations don’t vary between the supply voltage and zero:

Self-awareness of clock accuracy

The PCF8563 monitors the oscillator and supply voltage, and if the oscillator stops or the voltage drops below a certain point – the first bit of the seconds register (called the VL bit) is set to 1. Thus your sketch can tell you if there’s a chance of the time not being accurate by reading this bit. The default value is 1 on power-up, so you need to set it back to zero after setting the time in your sketch – which is done when you write seconds using the code in our example sketches. Then from that point it can be monitored by reading the seconds register, isolating the bit and returning the value.

Examine the function checkVLerror() in the following example sketch. It reads the seconds byte, isolates the VL bit, then turns on D13 (the onboard LED) if there’s a problem. The only way to restore the error bit to “OK” is to re-set the time:

month=bcdToDec(Wire.read()&B00011111);// remove century bit, 1999 is over

year=bcdToDec(Wire.read());

}

voidcheckVLerror()

// this checks the VL bit in the seconds register

// and turns on D13 if there's a possible accuracy error

{

bytetest;

Wire.beginTransmission(PCF8563address);

Wire.write(0x02);

Wire.endTransmission();

Wire.requestFrom(PCF8563address,1);

test=Wire.read();

test=test&B10000000;

if(test==B10000000)

{

// error

digitalWrite(13,HIGH);

Serial.println("Uh-oh - possible accuracy error");

}else

if(test!=B10000000)

{

digitalWrite(13,LOW);

}

}

voidsetup()

{

Wire.begin();

pinMode(13,OUTPUT);

digitalWrite(13,HIGH);

Serial.begin(9600);

// change the following to set your inital time

second=0;

minute=42;

hour=11;

dayOfWeek=2;

dayOfMonth=13;

month=8;

year=13;

// comment out the next line and upload again to set and keep the time from resetting every reset

// setPCF8563();

}

voidloop()

{

readPCF8563();

Serial.print(days[dayOfWeek]);

Serial.print(" ");

Serial.print(dayOfMonth,DEC);

Serial.print("/");

Serial.print(month,DEC);

Serial.print("/20");

Serial.print(year,DEC);

Serial.print(" - ");

Serial.print(hour,DEC);

Serial.print(":");

if(minute<10)

{

Serial.print("0");

}

Serial.print(minute,DEC);

Serial.print(":");

if(second<10)

{

Serial.print("0");

}

Serial.println(second,DEC);

checkVLerror();

delay(1000);

}

And now for a demonstration of the error-checking at work. We have the PCF8563 happily returning the data to the serial monitor. Then the power is removed and restored. You see D13 on the Arduino-compatible board turn on and then the error is displayed in the serial monitor:

This function may sound frivolous, however if you’re building a real product or serious project using the PCF8563, you can use this feature to add a level of professionalism and instil confidence in the end user.

Alarm Clock

You can use the PCF8563 as an alarm clock, that is be notified of a certain time, day and/or day of the week – at which point an action can take place. For example, trigger an interrupt or turn on a digital output pin for an external siren. Etcetera. Using the alarm in the sketch is quite similar to reading and writing the time, the data is stored in certain registers – as shown in the following table from page seven of the data sheet:

However there is a catch – the MSB (most significant bit, 7) in the registers above is used to determine whether that particular register plays a part in the alarm. For example, if you want your alarm to include hours and minutes, bit 7 needs to be set to 1 for the hour and minute alarm register. Don’t panic – you can easily set that bit by using a bitwise OR (“|”) and B10000000 to set the bit on with the matching data before writing it to the register.

Checking if the alarm has occurred can be done with two methods – software and hardware. Using software you check bit 3 of the register at 0x01 (the “AF” alarm flag bit). If it’s 1 – it’s alarm time! Then you can turn the alarm off by setting that bit to zero. Using hardware, first set bit 1 of register 0x01 to 1 – then whenever an alarm occurs, current can flow into pin 3 of the PCF8563. Yes – it’s an open-drain output – which means current flows from the supply voltage into pin 3. For example if you want to turn on an LED, connect a 560Ω resistor between 5V and the anode of the LED, then connect the cathode to pin 3 of the PCF8563. To turn off this current, you need to turn off the alarm flag bit as mentioned earlier.

Now let’s put all that into a demonstration sketch. It’s documented and if you’ve been following along it shouldn’t be difficult at all:

month=bcdToDec(Wire.read()&B00011111);// remove century bit, 1999 is over

year=bcdToDec(Wire.read());

}

voidsetup()

{

Wire.begin();

Serial.begin(9600);

// change the following to set your initial time

second=50;

minute=44;

hour=13;

dayOfWeek=1;

dayOfMonth=19;

month=8;

year=13;

// comment out the next line and upload again to set and keep the time from resetting every reset

setPCF8563();

alarmMinute=45;

alarmHour=13;

// comment out the next line and upload again to set and keep the alarm from resetting every reset

setPCF8563alarm();

}

voidloop()

{

readPCF8563();

Serial.print(days[dayOfWeek]);

Serial.print(" ");

Serial.print(dayOfMonth,DEC);

Serial.print("/");

Serial.print(month,DEC);

Serial.print("/20");

Serial.print(year,DEC);

Serial.print(" - ");

Serial.print(hour,DEC);

Serial.print(":");

if(minute<10)

{

Serial.print("0");

}

Serial.print(minute,DEC);

Serial.print(":");

if(second<10)

{

Serial.print("0");

}

Serial.println(second,DEC);

delay(1000);

// alarm?

checkPCF8563alarm();

}

This is the same as the example 54.1, however we’ve added the required functions to use the alarm. The required alarm data is stored in the global bytes:

Arduino

1

bytealarmMinute,alarmHour,alarmDay,alarmDayOfWeek;

and is written to the PCF8563 using the function:

Arduino

1

voidsetPCF8563alarm()

Note the use of bitwise OR (“|”) to add the enable bit 7 to the data before writing to the register. The interrupt pin is also set to activate at the end of this function, however you can remove that part of the code if unnecessary. We also demonstrate checking the alarm status via software using the function:

Arduino

1

voidcheckPCF8563alarm()

which simply reads the AF bit in the register at 0x01 and let’s us know if the alarm has occurred via the Serial Monitor. In this function you can add code to take action for your required needs. It also calls the function:

Arduino

1

voidPCF8563alarmOff()

which retrieves the contents of the register at 0x01, sets the AF bit to zero and writes it back. We do this to preserve the status of the other bits in that register. For the curious and non-believers you can see this sketch in action through the following video, first the software and then the hardware interrupt pin method (an LED comes on at the alarm time and is then turned off:

Conclusion

Hopefully you found this tutorial useful and now have the confidence to use the PCF8563 in your own projects. Furthermore I hope you learned something about the I2C bus and can have satisfaction in that you didn’t take the lazy option of using the library. People often say to me “Oh, there’s a library for that”, however if you used every library – you’d never learn how to interface things for yourself. One day there might not be a library! And then where would you be? So learning the hard way is better for you in the long run. If you have any questions leave a comment below, or ask privately via the contact page.

And if you enjoy my tutorials, or want to introduce someone else to the interesting world of Arduino – check out my book (now in a second printing) “Arduino Workshop” from No Starch Press.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, 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.

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:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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

voidsetup()

{

Wire.begin();

}

voidloop()

{

for(inti=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(inti=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:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

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

};

voidsetup()

{

Wire.begin();

}

voidloop()

{

for(inti=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:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

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

bytevalue0,value1,value2,value3;

voidsetup()

{

Wire.begin();

Serial.begin(9600);

}

voidloop()

{

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:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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

bytevalue0,value1,value2,value3;

voidsetup()

{

Wire.begin();

Serial.begin(9600);

}

voidloop()

{

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 twitter, Google+, 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.

In this article we investigate controlling the NXP (formerly Philips) SAA1064 4-digit LED display driver IC with Arduino and the I2C bus interface. If you are not familiar with using the I2C bus, please read my tutorials (parts one and two) before moving on. Although the SAA1064 is not the newest on the market, it is still popular, quite inexpensive and easy to source. Furthermore as it is controlled over the I2C bus – you don’t waste any digital I/O pins on your Arduino, and you can also operate up to four SAA1064s at once (allowing 16 digits!). Finally, it has a constant-current output – keeping all the segments of your LED display at a constant brightness (which is also adjustable). So let’s get started…

Here is an example of the SAA1064 in SOIC surface mount packaging:

It measures around 15mm in length. For use in a solderless breadboard, I have soldered the IC onto a through-hole adaptor:

The SAA1064 is also available in a regular through-hole DIP package. At this point, please download the data sheet (.pdf) as you will need to refer to it during the article. Next, our LED display examples. We need common-anode displays, and for this article we use two Agilent HDSP521G two-digit modules (data sheet [.pdf]) as shown below:

For the uninitiated – a common anode display has all the segments’ anodes connected together, with the cathodes terminated separately. For example, our LED displays are wired as such:

Notice the anodes for the left digit are pin 14, and the right digit pin 13. A device that is connected to all the cathodes (e.g. our SAA1064) will control the current flow through each element – thereby turning each segment on (and controlling the brightness) or off. Our SAA1064 is known as a current-sink as the current flows through the LED, and then sinks into the IC.

Now, let’s get it connected. There is an excellent demonstration circuit on page twelve of the data sheet that we will follow for our demonstrations:

It looks pretty straight-forward, and it is. The two transistors are standard NPN-type, such as PN2222. The two transistors are used to each turn on or off a pair of digits – as the IC can only drive digits 1+3 or 2+4 together. (When presented in real life the digits are numbered 4-3-2-1). So the pairs are alternatively turned on and off at a rapid rate, which is controlled by the capacitor between pin 2 and GND. The recommended value is 2.7 nF. At the time of writing, I didn’t have that value in stock, so chose a 3.3 nF instead. However due to the tolerance of the ceramic capacitor it was actually measured to be 2.93 nF:

So close enough to 2.7 nF will be OK. The other capacitor shown between pins 12 and 13 is a standard 0.1 uF smoothing capacitor. Pin 1 on the SAA1064 is used to determine the I2C bus address – for our example we have connected it straight to GND (no resistors at all) resulting in an address of 0x70. See the bottom page five of the data sheet for other address options. Power for the circuit can be taken from your Arduino’s 5V pin – and don’t forget to connect the circuit GND to Arduino GND. You will also use 4.7k ohm pull-up resistors on the SDA and SCL lines of the I2C bus.

The last piece of the schematic puzzle is how to connect the cathodes of the LED displays to the SAA1064. Display pins 14 and 13 are the common anodes of the digits.

Once your connections have been made, you could end up with spaghetti junction like this…

Now it is time to consider the Arduino sketch to control out SAA1064. Each write request to the SAA1064 requires several bytes. We either send a control command (to alter some of the SAA1064 parameters such as display brightness) or a display command (actually display numbers). For our example sketches the I2C bus address “0x70 >> 1” is stored in the byte variable saa1064. First of all, let’s look at sending commands, as this is always done first in a sketch to initiate the SAA1064 before sending it data.

As always, we send the address down the I2C bus to awaken the SAA1064 using

Arduino

1

Wire.beginTransmission(saa1064);

Then the next byte is the instruction byte. If we send zero:

Arduino

1

Wire.write(B00000000);

… the IC expects the next byte down the bus to be the command byte. And finally our command byte:

Arduino

1

Wire.write(B01000111);

The control bits are described on page six of the data sheet. However – for four-digit operation bits 0, 1 and 2 should be 1; bit 3 should be 0; and bits 4~6 determine the amount of current allowed to flow through the LED segments. Note that they are cumulative, so if you set bits 5 and 6 to 1 – 18 mA of current will flow. We will demonstrate this in detail later on.

Next, to send actual numbers to be displayed is slightly different. Note that the digits are numbered (from left to right) 4 3 2 1. Again, we first send the address down the I2C bus to awaken the SAA1064 using

Arduino

1

Wire.beginTransmission(saa1064);

Then the next byte is the instruction byte. If we send 1, the next byte of data will represent digit 1. If that follows with another byte, it will represent digit 2. And so on. So to send data to digit 1, send

Arduino

1

Wire.write(B00000001);

Although sending binary helps with the explanation, you can send decimal equivalents. Next, we send a byte for each digit (from right to left). Each bit in the byte represents a single LED element of the digit as well as the decimal point. Note how the elements are labelled (using A~G and DP) in the following image:

The digit bytes describe which digit elements to turn on or off. The bytes are described as such: Bpgfedcba. (p is the decimal point). So if you wanted to display the number 7, you would send B00000111 – as this would turn on elements a, b and c. To add the decimal point with 7 you would send B10000111. You can also send the byte as a decimal number. So to send the digit 7 as a decimal, you would send 7 – as 00000111 in base-10 is 7. To include the decimal point, send 135 – as 100000111 in base-10 is 135. Easy! You can also create other characters such as A~F for hexadecimal. In fact let’s do that now in the following example sketch:

Wire.write(1);// instruction byte - first digit to control is 1 (right hand side)

Wire.write(digits[z]);// digit 1 (RHS)

Wire.write(digits[z]);// digit 2

Wire.write(digits[z]);// digit 3

Wire.write(digits[z]);// digit 4 (LHS)

Wire.endTransmission();

delay(500);

}

// now repeat but with decimal point

for(intz=0;z<16;z++)

{

Wire.beginTransmission(saa1064);

Wire.write(1);// instruction byte - first digit to control is 1 (right hand side)

Wire.write(digits[z]+128);// digit 1 (RHS)

Wire.write(digits[z]+128);// digit 2

Wire.write(digits[z]+128);// digit 3

Wire.write(digits[z]+128);// digit 4 (LHS)

Wire.endTransmission();

delay(500);

}

}

voidclearDisplay()

// clears all digits

{

Wire.beginTransmission(saa1064);

Wire.write(1);// instruction byte - first digit to control is 1 (right hand side)

Wire.write(0);// digit 1 (RHS)

Wire.write(0);// digit 2

Wire.write(0);// digit 3

Wire.write(0);// digit 4 (LHS)

Wire.endTransmission();

}

voidloop()

{

displayDigits();

clearDisplay();

delay(1000);

}

/* **** We bitshift the address as the SAA1064 doesn't have the address 0x70 (ADR pin

to GND) but 0x38 and Arduino uses 7-bit addresses- so 8-bit addresses have to

be shifted to the right one bit. Thanks to Malcolm Cox */

In the function initDisplay() you can see an example of using the instruction then the control byte. In the function clearDisplay() you can see the simplest form of sending digits to the display – we send 0 for each digit to turn off all elements in each digit. The bytes that define the digits 0~9 and A~F are stored in the array digits[]. For example, the digit zero is 63 in decimal, which is B00111111 in binary – which turns on elements a,b,c,d,e and f. Finally, notice the second loop in displayDigits() – 128 is added to each digit value to turn on the decimal point. Before moving on, let’s see it in action:

Our next example revisits the instruction and control byte – we change the brightness of the digits by setting bits 4~6 in the control byte. Each level of brightness is separated into a separate function, and should be self-explanatory. Here is the sketch:

Wire.write(0);// instruction byte - Zero means the next byte is the control byte

Wire.write(B01001111);// set current and bit 3 to 1 for all segments on

Wire.endTransmission();

// now loop through the brightness levels

do

{

init3ma();

delay(d);

init6ma();

delay(d);

init9ma();

delay(d);

init12ma();

delay(d);

init18ma();

delay(d);

init21ma();

delay(d);

}

while(1>0);

}

And again, see it in action:

For our final example, there is a function displayInteger(a,b) which can be used to easily display numbers from 0~9999 on the 4-digit display. The parameter a is the number to display, and b is the leading-zero control – zero – off, one – on. The function does some maths on the integet to display and separates the digits for each column, then sends them to the SAA1064 in reverse order. By now you should be able to understand the following sketch:

So there you have it – another useful IC that can be used in conjunction with our Arduino systems to make life easier and reduce the required digital output pins.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our 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.

In this article we review the mbed NXP LPC1768 development board and the mbed system in general.

Introduction

Today we will examine the mbed NXP LPC1768 development board. The goal of the mbed system is to “provide(s) a platform for microcontroller hardware, tools, libraries and resources designed to enable rapid prototyping with microcontrollers.” (http://mbed.org/handbook/About). Personally I also see this as a good option for a “next step” for those who have outgrown their Arduino – the mbed offers much more processing power, a similar development environment and similar hardware ease of use. A great way to move from 8-bit to 32-bit power…

The NXP LCP1768 MCU on our mbed board offers the following specifications:

a Cortex-M3 core running at 96MHz

512kb flash memory and 64kb RAM

powered via USB or 4.5~9V DC applied straight to the board

Real time clock (requires external battery backup if necessary)

Loads of I/O options, including:

USB serial

I2C

Ethernet on board

SPI

serial I/O

Control-area network (CAN) bus

3.3v digital logic, 40mA per digital pin with a total maximum of 400 mA

Although a small project started by two ARM employees, the mbed has proven to be a worthy product to allow people of generally all skill levels access to powerful microcontrollers without a lot of the inherent complications. It does this in two ways:

Firstly, the hardware is very simple and designed for ease of use. The LPC1768 is mounted on a small board to convert it to a DIP format, making breadboard easy. The designers have also thought to include four blue LEDs for digital output and a nice large reset button. Interface with the PC is via USB. The mbed appears as a USB flash drive to your computer’s operating system, and compiled programs are downloaded as a single .bin file into the mbed.

Secondly, the development environment. Unlike other MCU products on the market, mbed is a completely online development environment. That is, in a manner very similar to cloud computing services such as Google Docs or Zoho Office. However there are some pros and cons of this method. The pros include not having to install any software on the PC – as long as you have a web browser and a USB port you should be fine; any new libraries or IDE updates are handled on the server leaving you to not worry about staying up to date; and the online environment can monitor and update your MCU firmware if necessary. However the cons are that you cannot work with your code off-line, and there may be some possible privacy issues. We will examine the online environment later on.

Preparing and using the mbed is incredibly simple. The designers have certainly exceeded their goal of providing a rapid prototyping environment. The process from opening the box to running your first program is (as always) quite simple.

The initial packaging is clear and inviting, and includes a getting started document, USB cable, a laminated hardware pinout card (very useful) and a bumper sticker (!):

The mbed unit itself is compact yet not too small:

The underside contains the USB interface and flash drive controllers:

The initial setup requires registration with the mbed online environment. This is done by plugging in your mbed to the USB, and visiting the web page URL stored in the mbed’s flash drive:

This will take you to the login page where you can create a new user profile:

The serial number of the mbed is recognised and linked to your user account. This means you do need to own an mbed to explore the depths of the online services available, and also serves to keep the mbed online ecosystem free of spammers and whatnot. After registration, you will be presented with the “getting started” page, which contains links to the function references, tutorials, FAQs, user forums, user-contributed content and more. All is revealed by exploring the links from this page.

After signing up, you can create a profile page which is public. This also contains tabs that contain notes, published (programs you make public) and libraries (that you have made public) Initially I thought the profile page would be private, or limited to other mbed owners, but this is not the case. From this page you can create notebook files, view your past activity and display published programs and libraries.

For example, I created a test notebook page and someone left a comment on it twenty minutes later. So be careful if you have some secrets – instead, you could cut and paste work to and from the IDE. However if you accidentally publish something it can be deleted, but remember that the internet is written in ink, not pencil.

However don’t let privacy worries put you off – just be careful not to write anything or publish programs you want to keep secret. Furthermore, as said earlier – having an online IDE has a few advantages – you don’t need to install anything on your PC apart from an up to date web browser. This means you can work on programs from other computers with ease. Bored at work? Using a locked-down hotel or school computer? You can still work on your mbed programs!

The openness of the mbed environment does create a positive, helpful environment similar to that found in the open-source community – there are many libraries that have been submitted that allow connection to various pieces of hardware such as LCD screens, bluetooth, Wii controllers, motors, servos, sensors and so on – as well as libraries for pachube, twitter, HTTP client and server access, and much more. These are found in the environment’s “Cookbook” section. If something interesting is on the market, there may very well be an mbed library to work with it.

The IDE is quite clear and straightforward. The program editor maintains colour-context, line numbering, support auto-formatting, and you can import or export code using the standard copy and paste keyboard shortcuts.

You can have multiple folders open at once, where each folder contains one program, the standard mbed function library and others you may have imported. Furthermore, there is also a very clear function reference for the standard mbed library available within the IDE – very useful. Programs are written in C++, and the online IDE takes care of everything – leaving you with only the .bin file to upload to the mbed. If you are new to programming or a little rusty with C++, books with unfortunate titles such as “C++ for Dummies” may prove useful.

You can also import libraries published by other mbed users into your own projects. Details of these published libraries (and programs) are listed in the mbed online environment. The speed of development is demonstrated very well in this video from the mbed team:

The support options are very good, including a members-only forum, loads of information, the Cookbook, a wiki for publishing user-contributed libraries and resources, and other FAQs and so on. If you have a question I am sure it could be answered very quickly. When it comes time to compile and run your program, after a successful compile your computer will download a single .bin file, which is then copied over to your mbed. Then by pressing the reset button on the mbed, the program is stored into the MCU and executed. You can store more than one .bin file on the mbed, however the latest file (by time stamp) is only executed.

Overall the mbed is a refreshingly-easy point of entry to microcontrollers. The ability to quickly prototype an idea into reality is really not difficult, and those with some C++ experience (or willing to learn) will make use of the mbed environment in no time at all. And if you decide to move your prototype into production, details and schematics are provided to help implement the nxp LPC1768 into your designs. Frankly, for fast prototyping at work, or just fun for anyone interested in electronics, the mbed offers a simple yet powerful way of getting things done.

The mbed board used in this review was a promotional consideration from RS. You can purchase an mbed directly from your local RS distributor.

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, 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.

Today we are going to examine the 74HC238 decoder/demultiplexer IC. My reason for writing this was to examine another way to get more output pins when using an Arduino or compatible board. However you can use any combination of three logic lines to turn on or off eight mutually exclusive outputs. How? Let’s find out…

First of all, here is the IC:

It is also available in SO16, SSOP16, TSSOP16 and DHVQFN16 packages. What? Here is a good list of various SMD packaging types. The pin layout is very simple, apart from +5V and ground, you have six pins that control the outputs, and eight output pins, however in reality you only need to control three from the microcontroller or other logic lines. Here is the pinout diagram:

To get the output pins high, you use a combination of levels on 74HC238 pins A0~A2 and possibly E3. If you leave E3 low, no outputs can be set to high. The input combination required for each output is described in this table from the data sheet:

Notice that columns with an X can be set either high or low, but you must not leave them floating, so always connect or set an X to high or low. If you need to have active low outputs (that is, outputs are high instead of low), there is the 74HC138. So now to do this in real life! Here is a demonstration schematic to use the 74HC238 with an Arduino Uno or 100% compatible board:

… and in real life:

And here is a demonstration video, using the following sketch:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

/*

Demonstrating use of 74HC238 with Arduino

John Boxall - http://tronixstuff.com/partreviews > 74HC238

16 July 2010

74HC238 pinouts:

Y0~Y7 > 39 ohm resistor > LED (3.2V forward voltage) > ground;

A0~A2 >> Arduino digital 2~4

E1, E2 >> ground

E3 > Arduino digital 5

16 > +5V

*/

intA0=2;

intA1=3;

intA2=4;

intE3=5;

intd=0;// for delay

voidsetup()

{

pinMode(A0,OUTPUT);

pinMode(A1,OUTPUT);

pinMode(A2,OUTPUT);

pinMode(E3,OUTPUT);

}

voidallLow()

// sets all outputs to LOW

{

digitalWrite(E3,LOW);

}

voidturnOn(intoutputPin)

// turns on output at pin 'outputPin'

{

digitalWrite(E3,HIGH);// enables outputs

switch(outputPin)

{

case0:

digitalWrite(A0,LOW);

digitalWrite(A1,LOW);

digitalWrite(A2,LOW);

break;

case1:

digitalWrite(A0,HIGH);

digitalWrite(A1,LOW);

digitalWrite(A2,LOW);

break;

case2:

digitalWrite(A0,LOW);

digitalWrite(A1,HIGH);

digitalWrite(A2,LOW);

break;

case3:

digitalWrite(A0,HIGH);

digitalWrite(A1,HIGH);

digitalWrite(A2,LOW);

break;

case4:

digitalWrite(A0,LOW);

digitalWrite(A1,LOW);

digitalWrite(A2,HIGH);

break;

case5:

digitalWrite(A0,HIGH);

digitalWrite(A1,LOW);

digitalWrite(A2,HIGH);

break;

case6:

digitalWrite(A0,LOW);

digitalWrite(A1,HIGH);

digitalWrite(A2,HIGH);

break;

case7:

digitalWrite(A0,HIGH);

digitalWrite(A1,HIGH);

digitalWrite(A2,HIGH);

break;

}

}

voidemulateKITT(intdd)

{

for(inti=0;i<8;i++)

{

turnOn(i);

delay(dd);

}

for(inti=7;i>=0;--i)

{

turnOn(i);

delay(dd);

}

allLow();

}

voidallOn(intdd)

// scans all outputs on to emulate all being on at once for 'dd' cycles

{

for(intj=0;j<dd;j++)

{

for(inti=0;i<8;i++)

{

turnOn(i);

}

}

allLow();

}

voidloop()

{

emulateKITT(100);

delay(1000);

allOn(10000);

delay(1000);

}

As with most other ICs of this type, you can only source 25 milliamps of current from each output, so if you need more you will have to consider the use of a switching NPN transistor etc. Although only one output can be high at a time, if you scan them quick enough, you can create the illusion that all are on at once (as in the video). Apart from LEDs and other items, you could use this IC to control stepper motors or even create a safe working environment on a model train layout.

To conclude, the 74HC238 offers one of several ways to control more things with less control pins. Ideal for mutually exclusive outputs, however if you needed more than one high at once, the 74HC595 shift register would be the better solution. (See here for a 74HC595 tutorial).

As always, have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, 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

Today we are going to examine the 74HC4066 quad bilateral switch IC. My reason for writing this comes from a comment left by a reader on chapter nine of the Arduino tutorial. They suggested using a 4066 IC to control the cathodes of the LED matrix instead of resistors and NPN transistors. This was a good suggestion, however the 4066 can only switch a current of 10mA per pin. Luckily the 74HC4066 can handle up to 25mA per switch – so we’ll look into this instead.

First of all, let’s say hello:

This is the 14-pin DIP package. It is also available in surface mount, and other newer package styles. Although we are looking at an example from NXP, according to my main component supplier (element-14/Newark) this IC is also manufactured by Texas Instruments, ON Semi, ST Microelectronics and Fairchild. So, what is a quad-bilateral switch? Four switches in one IC. Here is a diagram:

Imagine a simple normally-open push button. You press the button, and current can flow through the switch. Using the 74HC4066, when current is applied to the E pin, current can pass through from the matching Y pin to the Z pin. As you can see above, there are four of these switches in the IC. This is where the benefit of the IC comes to mind, normally one might use a 1k ohm resistor and an NPN switching transistor as an electronic switch, and I have done so myself. But when you need a few of them, it can be easier to start using these 74HC4066s as long as the current requirements are met.

With regards to the current the IC can switch, Is, the maximum is 25mA per switch. This is more than enough to run a typical LED, TTL logic gate, etc. The other interesting parameter is the turn-on and turn off times – at 6 volts it can turn on in around 10 nanoseconds and turn off at around 13 nanoseconds (so a rough calculation – say it takes 30 nanoseconds to switch on and then switch off, that’s 33.3 million times per seconds (33.3 MHz). All these parameters and more are available from the data sheet (pdf). Someone correct me if I’m wrong!

That’s enough theory – let’s put it to work now. Our first demonstration is quite simple – just switch on and off some LEDs via a 74HC595 shift register and an Arduino. We send a number (0, 1, 2, 4, 8 ) to the shift register, which stays off, then sets pins Q0, Q1, Q2, Q3 high in order, which in turn activate the switches 1~4 on the 74HC4066. The 74HC4066 sends a current to each LED connected to the switch outputs.

Here is the schematic:

Laid out on the breadboard:

And the ubiquitous video:

And here is the Arduino sketch: demo1.pdf. Well that was interesting. I know these simple demonstrations may be… well a little simple, but after taking the time to build them from scratch you get a better understanding of the part and how they work. Practice makes perfect and all that. Anyhow, let’s have a look at something much more interesting – a very basic (!) digital to analogue converter. Consider the circuit below:

The 74HC4066 switches creates a final voltage through the sum of various currents being switched into the final output. First of all, here is a video of the switches being turned on and off one at a time:

and the corresponding Arduino sketch:demo2.pdf. The next video shows the results of sending decimal numbers 0~15 to the shift register – in effect continually adding the outputs of the pins until all pins are on, then in reverse:

Well I hope you found this part review interesting, and helped you think of something new to make. In conclusion I would consider the 74HC4066 easier and quicker for end user to use in projects (less pins to solder, etc) however using it could cost more depending on the volume required. Furthermore, this would only apply if the current restrictions of the IC are met.

So have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our 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.

Notes: In writing this post, I used information from NXP, plus information and circuit inspiration from various books by Forrest Mims III.