Friday, 22 November 2013

Knock Clock with DS1307 continued!

Last post we designed a circuit to make a knock clock....Here is the circuit construction process:

1.  Obtain copper clad circuit board and print out bottom layer reversed on 120gm glossy paper using a laser printer.

2.  Using a clothes Iron to transfer bottom layer design to copper clad board.


3.  Once the design has been transferred soak off the excess paper with water to leave only the required copper.  Then etch the PCB using the preferred etchant - I used Ferric Chloride.


4.  After twenty minutes or so the copper should be etched away - monitor the process closely


5.  Once the etching is complete clean off the black ink using something abrasive - I used steel wool.  


6.  Finally drill out the holes using suitable drill sizes.  I used 0.8mm for every hole and then increased the FET, regulator and screw terminal holes to 1mm.

7.  Next populate the PCB with the components.  Make sure the IC socket (if you are using one) is orientated correctly along with the FET and the regulator and diode.  All of the other components are reversible.


Once that is complete we are onto the next stage.  I have to admit at this point I applied 12Vdc to the input to see if the red LED would light - it shows all of the power supply section is working - it was after I removed the LED and connected it with the correct polarity.  I always seem to get something wrong!

Next I flashed the arduino bootloader onto the ATMEL 328p chip using a dedicated ATMEL chip programmer.  There are loads of instructions available on how to achieve this:

How to flash a bootloader onto an ATMEL 328p

Once that was complete I loaded blink onto the target IC and connected an LED between MOSI and GND.  The LED flashed on and off - SUCCESS!

After that moment of awesomeness I loaded the code that I have developed earlier to achieve the knock clock functionality required.  I have to admit I had already done this as I breadboarded the circuit before populating the PCB...

Before doing all of this I populated the DS1307 adafruit RTC kit following the instructions on their website. I also then set the time on device using the serial terminal.  The instructions for doing this are:

Adafruit DS1307-real-time-clock-breakout-board-kit

The final Knock Clock code was developed from several libraries and some fairly standard programming.

Here is the code:

/*
 * Langster's Knock Clock Code
 * Forked from the TimeRTC Library example
 * The Knock Sensor Example from the Arduino Library
 * and some simple code to drive the solenoid from  
 * the FET - 22-11-2013
 */

#include <Time.h>       // Include time.h library
#include <Wire.h>       // Include Wire.h
#include <DS1307RTC.h>  // Include DS1307.h Library

byte val = 0;           // Variable to store a byte value

int solenoidPin = 9;    // FET solenoid Gate is connected to Digital pin 9
int knockSensor = A0;   // Piezo sensor attached to analogue zero            
int THRESHOLD = 10;     // integer variable that sets knock sensitivity
int hoursLoop = 0;      // integer variable for hours loop
int minutesLoop = 0;    // integer variable for minutes loop


void setup()  {
  Serial.begin(9600);         // start serial terminal at 9600 baud for debugging
  while (!Serial) ;           // wait until Arduino Serial Monitor opens
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");

  pinMode(solenoidPin, OUTPUT); //Set solenoid pin as a digital output    
}

void loop()
{
    val = analogRead(knockSensor);     // check for a knock!
    if (val >= THRESHOLD) 
    {
      Serial.println("Knock!");        // knock detected!
      if (timeStatus() == timeSet) 
      {
        digitalClockDisplay();         // display the time on the serial terminal
        actuateSolenoid();             // Drive the FET to actuate the solenoid
      } 
    else 
      {
        Serial.println("The time has not been set.  Please run the Time");
        Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
        Serial.println();
        delay(4000);
      }
    }  
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
  delay(500);
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void actuateSolenoid()
{
int convertHours = hour();  //convert from 24hour clock to 12 hour clock 
    if (convertHours > 12)
        {
          convertHours = convertHours - 12;
        }
  
  Serial.print("convertHours: ");
  Serial.print(convertHours);
  Serial.println(" ");
  
  //drive FET to actuate solenoid for number of hours
  
  for (hoursLoop=1; hoursLoop <= convertHours; hoursLoop++)
    {
       Serial.print(hoursLoop);
       Serial.println(" ");
       digitalWrite(solenoidPin, HIGH);
       delay(500);
       digitalWrite(solenoidPin, LOW);
       delay(500);
    } 
    
    delay(1000);  //pause between hours knocks and minutes knock

  int convertMinutes = minute();         //convert minutes to tens of minutes
  convertMinutes = convertMinutes / 10;
  
  Serial.print("convertMinutes: ");
  Serial.print(convertMinutes);
  Serial.println(" ");
  
  //drive FET to actuate solenoid for number of minutes
    
    for (minutesLoop=1; minutesLoop <= convertMinutes; minutesLoop++)
    {
       Serial.print(minutesLoop);
       Serial.println(" ");
       digitalWrite(solenoidPin, HIGH);
       delay(500);
       digitalWrite(solenoidPin, LOW);
       delay(500);
    }

}

The code pretty simple and the comments should explain each section clearly.  Essentially the arduino constantly polls the piezo sensor for a knock.  If a knock is detected the time is read from the real time clock device (DS1307).  The Hour data is then converted from 24 Hour clock format to 12 Hour format and the Solenoid is actuated for the number of Hours.  There is a short delay and then the minutes data is converted to tens of minutes and again the solenoid is actuated for the number of minutes.  The program then loops back to the start polling the piezo sensor for another Knock!

I will post a video of the circuit working when I get a chance!  The next post will discuss making a laser cut box for the Knock Clock before final assembly!  That is it for now though - Enjoy Langster!



Sunday, 17 November 2013

Knock Clock Using DS1307 and an Arduino

Knock Clock!

A Knock Clock is a electro mechanical clock which tells the 'knocker' the time in audible 'knocks' to +/-10 minute accuracy.  My better half saw one of these recently and asked me to make her one.  This is my own implementation based on a circuit made by a member of the Manchester Hackspace - Paul Plowman!

The device itself is a basically a box with some electronics and a device for striking the side of the box to create the 'knock' sound.  In this case I am using an electromagnetic plunger known as a solenoid.  It is normally used to control valves or mechanical devices from an electronic controller.  An electro-mechanical relay is essentially made up of a solenoid and a switch.  More information about solenoids can be found via the internet and wikipedia!

Wikipedia's entry on Solenoids

The basic idea of the circuit is, as with most electronics:

  • Take an input (the user 'knocking on the enclosure). 
  • Process this input (tell the processor to output the current time). 
  • Provide some form of output (cause the solenoid to actuate the time in hours and tens of minutes).

In this case the input is going to be sense the user knocking on the enclosure using a piezo buzzer as a simple microphone.  Piezo crystals are a useful electrochemical crystalline structure which when force is exerted on the structure a high voltage low current signal is generated.  It is the main component used is electric stove gas lighters and certain types of cigarette lighter.  More wikipedia below:

Piezoelectricity

Once the input has been detected it is necessary to process this input and then provide an output.  To this end I am going to use the ever popular Atmel 328P microcontroller with the arduino bootloader.  However I am not going to design a shield this time as I wanted to try to keep the cost of construction down.  Using an arduino main board for every project can get expensive - even using clones is becoming expensive!  So we have an input which we then need to compare to a known value - time!  How does the microcontroller know what the time is?  We could set the time on the microcontroller via the serial terminal each time the device is connected to a computer or we could use an ethernet controller and use the same technique; we could hard code the time from when the microcontroller was programmed and use that - best make sure the power is never removed!  Or we could use a real time clock...I have decided to use a real time clock as this is in my opinion the best method to use ensuring that the clock keeps reasonable time.

Real time clocks are special integrated circuits which communicate via the I2C protocol directly to the microcontroller and are battery backed up which means that they are constantly powered by a small battery and never lose the time (once it has been set) even if power to the main circuit is removed.  The accuracy over time is not always great (they lose a second each month) and the battery normally lasts about 5 years. There are several real time clock modules available to buy and rather than implement the circuit for myself I have bought one of these modules to save time.  The real time clock device used in the module is based on the ubiquitous DS1307 by Maxim Semiconductor.

DS1307 datasheet

The module I am using was provided by the excellent and very helpful Adafruit Industries:

DS1307 RTC Kit

Now that we have a method of receiving and processing the input it is necessary to drive the output - a solenoid. Solenoids are fairly common devices and can be treated in much the same was as a relay - although a power hungry relay!  It often takes a lot of current to drive a solenoid and the circuit will need to provide significant power (voltage and current) in order to make the solenoid actuate.  The best way to achieve this is to use a Field Effect Transistor.  I have discussed FETS in previous blog posts so I'm not going to go through this again - please read my previous posts.

We need an N-Channel metal oxide silicon field effect transistor ( N-MOSFET) with the following parameters:

Vds - 12V - I have decided to use 12V as the main voltage input
Vgs threshold - up to 5V - we need a logic level FET capable of being driven from the microcontroller
Ids - 1A or higher - we need a device capable of driving the Solenoid
T0220 Package - I like big through hole parts - they are easy to solder!   

There are probably over a hundred devices that meet these requirements.  If we do a search using Farnell Electronic's parametric search facility the following results are found:


We could use any of these N Channel-MOSFET devices and the VGS threshold voltage is the most important parameter as we need the device to work from a 5V digital signal from the microcontroller.  As we don't have any particular preference I am going to choose the least expensive device to keep costs down and the cheapest device is one I already own!

The device I have chosen is the IRF630 by ST Microelectronics - the datasheet is below:

IRF630 Datasheet

It meets all of the requirements and costs a very reasonable £0.56 from Farnell Electronics.

So....we now have all of the parameters for the Knock Clock decided we can go ahead and design the circuit.  I have decided to use a basic implementation of the arduino using an Atmel 328p.  The circuit will not have the serial to USB converter or a method of programming the microcontroller so we will have to provide a method of programming and talking to the microcontroller.  The rest of the circuit is standard boiler plate electronics - A 12V to 5V linear regulator, a piezo electric speaker (being used as a microphone) and a MOSFET driving a solenoid.  The centre header is for the real time clock module. The circuit is shown below:

 
I have included a six pin programming header to initially 'flash' the arduino bootloader onto the microcontroller and a header to allow communication with the microcontroller via a USB to serial cable.  The 12Vdc input will be provided via a standard dc barrel jack or via 5mm screw terminals.  The output to the solenoid is provided also via 5mm screw terminals.

Here is the PCB layout for the bottom layer:


Here is the top layer with the component identification:


The bill of materials for this project is as follows:

Part Value Device Description
       
C1 22pF Ceramic capacitor Capacitor
C2 22pF Ceramic capacitor Capacitor
C3 0.1uF Electrolytic Capacitor Capacitor Polarized
C4 10uF Electrolytic Capacitor Capacitor Polarized
C5 10uF Electrolytic Capacitor Capacitor Polarized
C6 100nF Ceramic capacitor Capacitor
C7 100nF Ceramic capacitor Capacitor
D1 1N4001 Axial rectifier Diode
IC1 LM7805 T0220 package  Voltage Regulator
J1 Programming Header 6x 0.1' pitch header pins 6 pin I2C programming header
J2 12Vdc power jack 3.5mm dc power jack Power Jack
JP1 6 pin Header 6x 0.1' pitch header pins Serial Communications Header
JP2 5 pin Header 5x 0.1' pitch header pins RTC Header
JP3 5mm Screw Terminal 5mm screw terminal phoenix connector 12Vdc input from screw terminals
JP4 5mm Screw terminal 5mm screw terminal phoenix connector Solenoid output from MOSFET
KK1 Heatsink T0220 Heatsink Heatsink for MOSFET
LED1 5mm Red LED 5mm Red LED Power LED
Q1 IRF630 MOSFET N-CHANNEL Common logic level MOSFET
R1 10k 1/4W axial resistor Resistor
R2 220R 1/4W axial resistor Resistor
R3 1k 1/4W axial resistor Resistor
R4 100k 1/4W axial resistor Resistor
R5 1M 1/4W axial resistor Resistor
S1 Microswitch momentary tactile switch Momentary Switch for reset
SP1 Piezo Buzzer Piezo Buzzer Piezo Buzzer used as a microphone
U1 ATMEGA328P ATMEGA328P - DIP package Microcontroller with arduino bootloader
Y1 16MHz 16MHz crystal (through hole) 16MHz Crystal for microcontroller

Just for fun I used an online gerber viewer to show what the printed circuit boards will look like if manufactured:

Here is the Bottom Layer
Here is the top layer:
Well that is about all for now.  In the next post I will show pictures of the actual construction and then finally I'll go through the programming of the firmware for the microcontroller.  Enjoy - Langster!



Sunday, 6 October 2013

How do Switch-Mode Boost Converters Work

I recently made my own version of the adafruit Minty Boost circuit.  It's a battery powered DC to DC converter that takes 2x 1.5V AA batteries and converts that to 5V USB output.  It's a damn useful circuit particularly for use charging mobile telephones when the internal battery is running flat!  I find it slightly more useful than commercial versions of the same device because rather than using a lithium polymer battery this version uses off the shelf AA batteries which are nearly always available from any shop anywhere!  Lithium polymer batteries need special charging circuits and don't like being over and undercharged which is easily done.

The original circuit and some very good documentation and kits are available here:

MintyBoost V3.0 - Very cool stuff from Adafruit Industries!!!

The circuit is a switch-mode dc to dc converter.  I haven't talked about switch-mode power supplies before so here goes!  This might get complicated....bear with me!

Power supplies can be realised in several different forms:

Step UP - Increase voltage or current
Step Down - reduce voltage or current
ac - alternating current
dc - direct current
Linear - conversion in a straight line...see previous posts
Switch-mode - use a combination of an inductor, zener diode and capacitor to provide a different voltage than the input.

Switch-mode power supplies are based on an electronic trick...What they do is take energy in one form and convert it to another form to get the desired output.  How they work is they take a dc voltage source (input) convert it to a pseudo alternating signal (square wave or pulse width modulation) and pass that signal through a combination of an inductor, switching diode and capacitor.  The way the inductor diode and capacitor are connected denotes the type of switch-mode power supply.  This is known as the switch-mode topology....Some examples of these are:

Buck (Step Down)
Boost (Step Up)
Flyback (Step Up)

A Buck regulated switch-mode power supply (SMPS) would take in say 12 V and give out 5 V at a steady current.

A Boost regulated SMPS takes in say a 3 V input and boosts it to 5 V

The circuit topology depends on how much power or energy the circuit designer requires.  SMPS are popular because they are more efficient than linear power supplies and use smaller and cheaper components. The drawback of switch-mode power supplies is that they have inherent electronic switching noise which can affect sensitive instrumentation circuitry.

Wikipedia has a great entry on how boost converters work:

http://en.wikipedia.org/wiki/Boost_converter

Here is a quick example simulation I made up just to show how boost converters work.  Essentially what they do is increase the output voltage by taking the input voltage, creating a switching waveform and passing that signal through an inductor, switching (Schottkey) diode and a large electrolytic capacitor.  By doing this the energy in the switching waveform is held as magnetic energy in the inductor for a very short period of time.  This energy then charges the capacitor up.  When the switching waveform changes polarity the energy in the capacitor is dumped to the output...this energy dumping is seen by the output as an increased voltage. The classic water analogy would be filling a large water tank very quickly with low pressure and then emptying it all in one go giving the impression there is more water pressure present at the output than at the source.

Here is the circuit:


Here is a simulation video showing the various parts of the circuit and the switching and output waveforms on an oscilloscope.





The section containing the signal generator and the TIP41CG transistor can be combined into a single integrated circuit called a boost converter.  The IC used in the circuit by Adafruit Industries in the mintyBoost was an LT1302 micropower Boost Converter.  Its a very useful device if a little expensive! It basically combines the chopper signal generator and switching transistor into one single device which is easy to use.

LT1302 product page

Here is the schematic diagram for the Adafruit minty Boost....I have redrawn it for my own nefarious purposes.  The component values and types are exactly the same as Adafruit used.


Here is my PCB layout.  It uses a single sided PCB to make it easy to etch using the toner transfer method


Just for fun I rendered the PCB in google Sketchup to show how the device will look once I have populated



Here it is again with a 2xAA battery holder and some mechanical dimensions - Renders are Cool!


These renders are very useful as they show the designer very clearly if the components will all fit together and not foul on each other.  It also makes it easy to design an enclosure for the circuitry once the design has been constructed and tested....something I really struggle with :(

Anyway....I made the circuit for real....for once it worked first time!  I am not surprised however as all of the hard work was done for me by Limor Fried of Adafruit industries....they do excellent work - Please check them out!

Here is a picture of the realised circuit!  The photograph is of a previous version I made with the PCB elongated to hold the battery compartment.  I decided to shorten the PCB for this version to reduce costs!


That's it for now.  Enjoy - Langster!


Saturday, 20 July 2013

Arduino LC Meter Shield

A short distraction from the Signal Generator project to make an LC Meter Shield!

It has been a considerable time since I posted.  Blogging does not come naturally for me and I often prefer to just do things rather than write about them.  I still haven't finished the Signal Generator although to be honest it is close....I am lacking motivation.  I have pushed that project down a route which is no longer palatable... 

Instead I have decided I will write about a small project that I made recently which works well and was great fun (for me) to make and build.  I always need test equipment....it's a strange thing with Engineers...they need toys to make bigger toys!

In order to measure Capacitance and Inductance a piece of test equipment is often used called an LC Meter.  This is a device which measures the amount of Henries an inductor has (Henries is the unit of inductance) or the amount of Farads in a capacitor (Farads is the unit of capacitance).

Inductor - an electronic component that stores energy for a short period of time by generating a magnetic field - normally made by making a coil of wire around a former.  Sometimes special cores are used to improve the inductor's frequency response.  Inductors are sometimes called chokes!

http://en.wikipedia.org/wiki/Inductors

Capacitor - an electronic component that stores energy for a short period of time by producing an electrostatic field on two metal plates.  The size of the plates and the distance between the plates changes the amount the of capacitance the component will have.  The dielectric material between the plates also has an effect of the amount of capacitance.

http://en.wikipedia.org/wiki/Capacitor

I needed a way of verifying that the electronic components I bought or made are within the specifications I require!  Component manufacturers print the nominal level of what the inductor or capacitor is but this varies considerably between batches and is often considerably off.  Every good engineer needs a way of checking that parts are what they say they are...

There are plenty of hobbyist projects available on making an LC meter.  This is my interpretation.  If you do a search in google for 'LC meter circuit' several pages will be sourced immediatly.

I was directly inspired by Kerry Wong's blog post -

Kerry Wong's Blog about an LC Meter

There was also an article in Everyday Practical Electronics issue in March 2010 using a PIC Microcontroller.

I decided to make an LC Meter which uses the arduino shield form factor and is easy to make and use.  I'm hoping people will like it and use it...although most electronics hobbyists I know nowadays are all digital and no analogue - ho hum!

Most LC meter instruments use a free running oscillator at a known frequency.  When the user inserts the component in question in parallel with the oscilllator  the frequency changes. By comparing the new frequency with the old frequency and using some mathematics the value for the component can be obtained.

So....how do we make an oscillator?  There are several methods and I have discussed this in previous blog posts.  This project uses a comparator to make a square wave oscillator.  The circuit is below:



The oscillator section is made up of the 100uH inductor and the 4.7nF Capacitor.  These two components decide the frequency of oscillation.  All the other components are to make the oscillator work and to provide a method of making measurements.

The formula for calculating the frequency of oscillation and the other formulae used in the project are below:



lets calculate the frequency of our oscillator:

L = 100 uH or 100 * 10^-6 H
C = 4.7 nF or 4.7 * 10^-9 F
PI = 3.142..

Therefore F = 1 / 6.284 * SQRT (100*10^-6 * 4.7*10^-9)

F = 232.121 kHz

lets say 232 kHz.

So our oscillator will free run at 232 kHz using the above inductor and capacitor.  If we then introduce another component into the oscillation this frequency will change and we can use the original frequency and information about the oscillator components to calculate what value the new component has.

Here is a short simulation video showing how the measurement stage works:



Now that we have a method of measuring the components we need a way of controlling the circuit and displaying the information.

To this end I am going to use the popular arduino platform because its a great piece of hardware for rapid prototyping!  Here is the rest of the circuit:



The circuit is fairly boiler plate electronics.  The frequency of the oscillator is measured by the arduino on pin 5.  The firmware uses a special arduino frequency counter library - more on this later.  The type of measurement is controlled by a switch selecting which type of component is being measured and then we also have two buttons for displaying the current frequency of oscillation or measurement function (which controls a relay) and a calibration / zero button.  We finally have an 16x2 LCD display being controlled by the arduino to display the information.

Once I had prototyped the circuit and checked it worked - briefly I laid out a PCB and etched a circuit board.  Here is the layout:
Top Layer with component placement
PCB Bottom Layer

I then etched and drilled the PCB and populated it with components.  I was so excited I plugged it onto my arduino and tried to get it working straight away...It didn't but that's not surprising.  If a project works first time nobody learns anything!  Sometimes though I do wish projects would work first time - particularly at work!

The problems were minor and have been fixed in the layout so if I decide to make another version it will work first time - Here is a link to the Eagle files and other associated information:

Google Drive link to LC Meter Eagle project - LM339 version

Once I had checked that the oscillator was working with an oscilloscope I got on with writing the source code.  I'm not the best programmer in the world so I used a lot of other people's work to get this circuit to work as intended.  Kudos to Kerry Wong and his version of this project!

The reason this project is viable is because of the frequency counter library made and maintained by Peter Welter-Platz

http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/

Updated Library for use with the latest Arduino IDE:

http://interface.khm.de/wp-content/uploads/2009/01/FreqCounter_1_12.zip

Updated Library for the reading the Button presses:

Its a great library and it makes it very easy for people to measure frequency of signals with their arduino.  Basically I believe the library works by comparing the frequency to be measured with one of the internal microcontroller timers.  The result is then stored and available for interrogation.

http://downloads.arduino.cc/libraries/github.com/madleech/Button-1.0.0.zip

In order to get the code to compile you will need to download the latest versions of these libraries and install them using the Arduino IDE.

Here is the code...it's not perfect but it does work:

/*
  Langster's LC Meter Code - 09-06-2019
  Uses the LCD library, Frequency Library 
  Button libary and various other bits and pieces

  Updated the code for use with updated libraries etc.
  
  V2.0 
  
  This code borrows from Kerry Wongs LC Meter
  code!
  
  To Calibrate press both the Frequency and 
  Calibrate buttons together!
  
  To measure frequency press the frequency
  button
  
  Enjoy!
   
 */

// Include the Frequency counter library
#include <FreqCounter.h>

// Include the Button Library
#include <Button.h>

//part of the switch position check
enum meterMode {
    L,
    C,
    F
};

unsigned long indFreq = 23896;   //rough frequency from oscilloscope measurements
unsigned long capFreq = 23885;   //rough frequency from oscilloscope measurements

long measureComponentFreq = 0;   //variable to store component measurement frequency

float cMeasured;                 //Th measured capacitance
double lMeasured;                //The measured inductance

float cMeasuredZero;             //The zero factor for capacitance
double lMeasuredZero;            //The zero factor for inductance

//Some temporary variables for calculations

long temp1;
long temp2;
double temp3;

const float Cth = 4.7 * 1e-9;    //measured 4.7nF - calibration capacitor value
const float Lth = 91.14 * 1e-6;  //measured 91.14uH - calibration inductor value

int i=0;                         // count variable
int switchState;                 // variable for storing the state of the switch

unsigned long frq;               //The frequency measurement
long capFreqArray[10];           //An array for storing frequencies
long indFreqArray[10];           //An array for storing frequencies

long frqAverage = 0;             //An variable for averaging
long average = 0;                

const int frequencyButtonPin = 16;     // the number of the pushbutton pin
const int calibrateButtonPin = 15;     // the number of the pushbutton pin
const int relayPin = 14;               // the number of the relay pin
const int componentSelectPin = 2;      // the number of the component select pin
const float pi2=6.283185307;

Button calibrationButton = Button(15);  //Calibration button on pin 15 or A1
Button frequencyButton = Button(16);    //Frequency button on pin 16 or A2

meterMode currentMode;                  //check which mode the switch is in

// include the LCD display library:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

//Check the switch position

void checkLCMode() {  
    
    switchState = digitalRead(componentSelectPin);
    
    if (switchState==LOW) {
        currentMode = L;
        lcd.setCursor(0, 0);
        lcd.print("Mode: L    ");
        measureInductance();
        
    } else {
        currentMode = C;
        lcd.setCursor(0, 0);
        lcd.print("Mode: C    ");
        measureCapacitance();
    }

}

//setup the arduino

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);

  pinMode(relayPin, OUTPUT);
  
  pinMode(calibrateButtonPin, INPUT);
  pinMode(frequencyButtonPin, INPUT);
  pinMode(componentSelectPin, INPUT);
  
  digitalWrite(componentSelectPin, HIGH);
  
  Serial.begin(57600);        // connect to the serial port
  digitalWrite(relayPin, HIGH); 

  lcd.setCursor(0, 0);
  lcd.print(" ** LC Meter ** ");
  
  //measureCalibrationCapacitance();
  //measureCalibrationInductance();
    
  delay(2000); 
  
  lcd.clear();
   
}  

void loop()
{
  //check if calibration is required
  
  if(calibrationButton.pressed() && frequencyButton.pressed())
  {
    switchState = digitalRead(componentSelectPin);
    
    if (switchState==LOW) 
      {
          currentMode = L;
          lcd.setCursor(0, 0);
          lcd.print("Short Terminals");
          lcd.setCursor(0, 1);
          lcd.print("Press Cal Button");
          
          if(calibrationButton.pressed())
            {
              measureCalibrationInductance();
            }
  
      } 
    
    if (switchState==HIGH) 
  
      {
          currentMode = C;
          lcd.setCursor(0, 0);
          lcd.print("Clear Terminals");
          lcd.setCursor(0, 1);
          lcd.print("Press Cal Button");
          
          if(calibrationButton.pressed())
            {
              measureCalibrationCapacitance();
            }
      }
      
  }
  
  //check if frequency measurement is required
  
  if(frequencyButton.pressed())
      {
        measureFrequency();
        digitalWrite(relayPin, HIGH);
      }

checkLCMode();    //check switch position
  
  
}

//Measure the frequency

void measureFrequency()
{

    digitalWrite(relayPin, LOW);
  
    FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
    FreqCounter::start(100);  // 100 ms Gate Time
    while (FreqCounter::f_ready == 0) 
    frq=FreqCounter::f_freq;   
    
    lcd.setCursor(0, 0);
    lcd.print("Frequency ");
    
    lcd.setCursor(0, 1);
    lcd.print("F: ");
    lcd.print(frq);
    lcd.print("      ");
     
    delay(4000);
    
}

//Calibrate for inductance measurements

void measureCalibrationInductance(){

    for (int i=0; i<100; i++)
        
        {
          FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
          FreqCounter::start(100);  // 100 ms Gate Time
          while (FreqCounter::f_ready == 0) 
          frq=FreqCounter::f_freq;
          indFreq=frq;
          
          temp1 = sq(indFreq);
          temp2 = sq(measureComponentFreq);
          temp3 = float(temp1)/float(temp2);
          lMeasured = Lth*(temp3-1);
          lMeasuredZero = lMeasured;
          i++;
          
        }
      
      lcd.setCursor(0, 0); 
      lcd.print("Calibration     ");
      lcd.setCursor(0, 1);
      lcd.print("Complete        ");
      delay(4000);
      
      lcd.clear();
    
}

//Measure the inductance

void measureInductance()

{
      FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
      FreqCounter::start(100);  // 100 ms Gate Time
      while (FreqCounter::f_ready == 0) 
      frq=FreqCounter::f_freq;
      measureComponentFreq=frq;
      
      delay(200);
      
      calcIndData();

}



//Calculate and Display the Inductance

void calcIndData(){
    
    temp1 = sq(indFreq);
    temp2 = sq(measureComponentFreq);
    temp3 = float(temp1)/float(temp2);
    lMeasured = Lth*(temp3-1) - lMeasuredZero;
    
    lcd.setCursor(0, 1);
    lcd.print("L: ");    
        
     if (lMeasured >= 1e-9 && lMeasured < 1e-6) 
            {
                lMeasured = lMeasured * 1e9; // nano
                lcd.print(lMeasured);
                lcd.print(" ");
                lcd.print("nH");
                lcd.print("        ");
            } 
            
            if (lMeasured > 1e-6 && lMeasured < 1e-3) 
         
            {
                lMeasured = lMeasured * 1e6; // micro
                lcd.print(lMeasured);
                lcd.print(" ");
                lcd.print("uH");
                lcd.print("        ");
            }
            
            
            if (lMeasured > 1e-3) 
            
            {
                lMeasured = lMeasured * 1e3; // milli
                lcd.print(lMeasured);
                lcd.print(" ");
                lcd.print("mH");
                lcd.print("        ");
            }
  
}  

//Measure the Calibration Capacitance

void measureCalibrationCapacitance()
{
  for (int i=0; i<100; i++)
        {
          FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
          FreqCounter::start(100);  // 100 ms Gate Time
          while (FreqCounter::f_ready == 0) 
          frq=FreqCounter::f_freq;
          capFreq=frq;
          
          temp1 = sq(capFreq);
          temp2 = sq(measureComponentFreq);
          temp3 = float(temp1)/float(temp2);
          cMeasured = Cth *(temp3-1);
          cMeasuredZero = cMeasured;
          i++;
        }
     
     lcd.setCursor(0, 0); 
     lcd.print("Calibration     ");
     lcd.setCursor(0, 1);
     lcd.print("Complete        ");
     delay(4000);
     
     lcd.clear();
     
}


//Measure the capacitance

void measureCapacitance(){
    
      FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
      FreqCounter::start(100);  // 100 ms Gate Time
      while (FreqCounter::f_ready == 0) 
      frq=FreqCounter::f_freq;
      measureComponentFreq=frq;
      
      delay(200);
      
      calcCapData();
    
}

//Calculate and display the capacitance
  
void calcCapData(){
    
    temp1 = sq(capFreq);
    temp2 = sq(measureComponentFreq);
    
    temp3 = float(temp1)/float(temp2);
    cMeasured = Cth*(temp3-1)-cMeasuredZero;
    
    Serial.print("Capacitor Oscillator Frequency: ");
    Serial.print(capFreq);
    Serial.println();
    Serial.print("Component Oscillator Frequency: ");
    Serial.print(measureComponentFreq);
    Serial.println();
    Serial.print("Cap Osc Squared: ");
    Serial.print(temp1);
    Serial.println();
    Serial.print("Msr Osc Squared: ");
    Serial.print(temp2);
    Serial.println();
    Serial.print("Division       : ");
    Serial.print(temp3);
    Serial.println();
    Serial.print("Component Value: ");
    Serial.print(cMeasured);
    Serial.println();
    
       
    lcd.setCursor(0, 1);
    lcd.print("C: ");
        
     if (cMeasured < 1e-9) 
            {
                cMeasured = cMeasured * 1e12; // pico
                lcd.print(cMeasured);
                lcd.print(" ");
                lcd.print("pF");
                lcd.print("       ");
            } 
            
     if (cMeasured >= 1e-9 && cMeasured < 1e-6) 
            
            {
                cMeasured = cMeasured * 1e9; // n
                lcd.print(cMeasured);
                lcd.print(" ");
                lcd.print("nF");
                lcd.print("       ");
            }  
            
      if (cMeasured > 1e-6)      
            {
                lcd.print("Out of Range");
                lcd.print("        ");
            } 
    
} 

It's long and it isn't pretty but it should be fairly simple to understand.  The program sets up the libraries, variables and the buttons and LCD display.  It then looks at which position the user component select switch is in and then performs the required measurement.  If the user presses the frequency button the current frequency of the oscillator is displayed.  If the user presses and holds both buttons and then follows the on screen instructions the unit calibrates.  In order to calibrate the L mode the input terminals have to be shorted together.  For capacitance mode the terminals must be open and not connected to anything.

Here is a video of the completed unit running on my arduino Uno in use.



There are things about the LC meter that I would do differently - there always are!  I would prefer the device to have a larger measurement range - Inductors are ok but the capacitance range of up to 1 µF is not helpful.  I often like to measure electrolytic capacitors and this unit can't do that.  In order to achieve that I need to implement a frequency divider circuit on the measurement frequency pin so that I can then use a smaller measurement capacitor which increases the range.  I would also like to add another relay which automatically shorts the measurement terminals so that when calibrating the inductor range the user doesn't have to short the terminals.  All told though this came out very well! 

Update: I got some valuable feedback from a reader who asked if it would be possible to implement the analogue section using a dual comparator.  It is possible and I have selected the LM393 dual comparator to do this.  Here is the full schematic:



I hope this helps people make their own versions of the circuit!  Here is a link to the LM311 Eagle Files:

LC Meter - LM311 Version Eagle Files

Further Updates:

I have had some feedback from quite a few people regarding this post...my most popular project yet! I have decided to help out by giving the bill of materials:


All of the part numbers are for Farnell Electronics.  I suggest people shop around for various parts as they can be found cheaper elsewhere - particularly the 16x2 LCD display and the Arduino.

Here is some 3D renders of the circuit I made using Eagle and Sketchup! I also made a case which can be 3D printed.







Update - A lot of people have been building this project (which is great!) but are sometimes struggling to check things are working as intended. If you have access to an oscilloscope you can measure the oscillation frequency by connecting the oscilloscope probe ground lead to any 0V reference on the circuit (I use the ground plane normally) and then connect the probe tip to pin 2 of the LM339 or pin 3 of an LM311.  Ensure that the measurement terminals are open (nothing is connected to them and the unit is in capacitance mode.  If the same 100 uH inductor and 4.7 nF capacitor have been used it should be possible to see the following waveform:

LC Meter Oscillator on Pin 2 with terminals open
If you want you can then short the terminals together and change the select switch and you should see exactly the same waveform!

The oscilloscope was set to 5 volts / division on the Y axis and the time base was set to 2 micro-seconds per division for the X axis.  The trigger level was set to 1 Volt and the channel was set to measure a DC signal.  Good Luck!

Sunday, 27 January 2013

Display and Control Section for AD9835 project

Now that the power supply and filter section for the function generator have been designed and realised it is time to concentrate on the control section.  We need a way of controlling the signal generator.  Lets discuss buttons!  We need buttons on the front panel for:

Select Sine Wave output
Select Square Wave output
Select Pulse Output
Turn the output On / Off
Select frequency
Select Amplitude
Select times 1 multiplier (units)
Select times 1000 multiplier (kilo)
Select times 1000000 multiplier (Mega)
Select increment (more)
Select decrement (less)

That is a lot of buttons!  We could use a keypad but I don't think it's really necessary in this particular situation.  What we need to keep in mind are the digital pin requirements for the microcontroller (arduino).  We have 12 digital pins available as standard and another 6 more if we use the analogue pins as digital pins which gives a maximum of 18 pins available to control the AD9835 breakout PCB, the 16x2 LCD display, the rotary encoder and all of the above buttons!  (I'm not including the RX and TX serial control pins)  See the table below:

Device Total Number of pins Number of arduino pins required
     
16x2 LCD Display 16 6
AD9835 breakout 8 6
Sine Button 4 1
Square Button 4 1
Pulse Button 4 1
units 4 1
thousands 4 1
millions 4 1
up 4 1
down 4 1
enter 4 1
frequency 4 1
amplitude 4 1
output 4 1
rotary encoder 5 3
     
Total   27

Hmm....27 digital pins needed and only 18 available!  What are we going to do?  Well...it all depends on how we would like to approach the problem.  We could remove some of the buttons and lose some of the less necessary control features.  We could remove the LCD display and control the device via the serial terminal.  We don't need a rotary encoder, we can use a potentiometer and then we have saved ourselves considerable pin requirements.  Personally I don't like this idea....losing all of those things will make our function generator very hard to use....In my experience people hate electronic devices that are hard to use!  If it doesn't make your life easy or there is something better on the market then people will avoid your product, buy someone else's or moan bitterly!  I know it doesn't matter as nobody will be buying this signal generator but it's always a good idea to keep in mind what other people think and do...that way when you are designing a commercial product you will consider all of the relevant design criteria.

Ok, so we are going to keep all of the above functionality and somehow get 27 digital arduino pins from 17.  To quote one of my favourite TV Characters (Balldrick from the Blackadder comedies) "Don't worry, I have a cunning plan!...."  We are going to invest in some multiplexing.  For the driving of the LCD display we are going to use a serial to parallel shift register - the venerable but always useful 74LS595!  I have posted about this device before.  It's very useful and in this case I'm going to use it to control the LCD in a 3 wire mode.  This means I have reduced our pin count by three pins.  Hey every little helps!

Next I'm going to invest in a parallel to serial shift register.  There are plenty to choose from but I have decided to stick with TTL (5V) logic and use the SN74HC165 - from Texas Instruments.


Sparkfun Electronics also handily sell a a breakout PCB for $3.95!  Not bad, the link is below:


This device takes 8 digital inputs and converts these inputs into serial data on 3 pins and then passes them to the microcontroller.  We then write some processing software which reads this serial data and use it for our own nefarious purposes!  I'm not going to use the breakout PCB although I could do.  I'm going to design a PCB for adding both inputs and outputs to the arduino and combine the 74HC595 and 74HC165 on one PCB.  I'm then going to use that PCB connected to the arduino to control the LCD display and buttons.  This adds another 16 inputs to our system but removes 3 therefore we now have 12 original arduino pins available and 16 dedicated outputs and 16 dedicated inputs.  This should be more than enough for the signal generator....the downside is it makes coding the control firmware on the microcontroller more difficult.     

There is a quicker and possibly cheaper alternative to all of this extra work....use an Arduino mega!  This is a different microcontroller and development board which has 52 digital inputs / outputs and has all the other requirements we need.  The only reason I'm not using one is because in this case I think its better to learn something rather than cheat and just use a bigger microcontroller...If anyone wants to use an arduino mega for their projects that also fine!

Here is the schematic for my I/O expander circuit - it could be used for many different application, not just for this project.  I also believe with some programming this PCB could be used with the Raspberry PI to add more GPIO pins.  


  The circuit basically takes the information given in the integrated circuit datasheets and applies this information to the arduino uno.  Serial data, clock and latch are provided for each device respectively.  With this circuitry we have added 16 digital outputs with the 74HC595 section and 16 inputs from the 74HC165 section.  In order to 'drive' each of these sections 6 digital pins will be required from the arduino.  6 digital I/O pins from 18 leaves 12 digital I/O pins left which should be more than enough for our requirements!

Here is the PCB layout.  If I'm honest this was a really hard circuit to lay out single sided.  I would have preferred to go dual layer however I can't fabricate this in my work shop.  I could get PCBS professionally made but I'm impatient.


Well....that's all for now, I'm going to build and test this PCB in the next few days and then I'll update the circuit to show how I'm going to use this PCB to drive the LCD display for the AD9835 signal generator.  Until then....Take care folks - Langster!





    

Tuesday, 22 January 2013

Power supply for function generator

Over the course of developing and testing the function generator I have needed a dual polarity power supply.  I have been using a bench power supply that I made some time ago.  It has two variable voltage outputs and I am linking the +ve terminal of one supply to the 0V of the other supply to create a dual +/- supply.  This is fine but I also needed a way of powering the arduino uno that I am using to control the AD9835 function generator PCB.  During the course of my testing in a massive 'ooops' moment, I managed to wire up something incorrectly and destroyed my arduino uno!  This is to be avoided obviously and I only have myself to blame!

Note to self....when testing or developing a project ensure that connecting power to the device under test is as simple and stress free as possible. A random mass of different coloured wires is Not acceptable!

Further note to self....ensure that the power supply you are using cannot supply too much voltage or current to the device under test!  This way no magic smoke or expensive and unnecessary catastrophic failures will be observed!

To stop this happening I have designed a power supply which meets all of these requirements and ensures that this shouldn't happen again - I am of course assuming that I won't make a similar mistake again and that is a significant assumption!  I often make mistakes....

The power supply is a linear power supply with the following features:

Take an input of 230V 50Hz AC (British AC line voltage)

and provide the following output:

+12V output with at least 500mA to power the op-amp filter and amplifier section
-12V output with at least 500mA to power the op-amp filter and amplifier section

+9V output with at least 500mA to power the arduino and display and control section - I know I could have used 5V here but I wanted to use slightly greater than 5V so that I am correctly powering the on board linear regulator already present on an arduino.  I'm going to use the 5V output for everything else.

With the power and functional specifications sorted I had a look at which parts I had available.    I didn't have any switching regulator devices handy and I didn't want to introduce more switching noise into my circuit.  I haven't made many switch-mode power supplies and didn't want to use this topology of power supply.   I did have plenty of linear regulators including a LM7809 and a LM7812 for positive voltage regulation and a LM7912 for negative voltage regulation.

Here are the datasheets for those devices:

Fairchild version of 78XX positive linear regulator datasheet

Fairchild version of 79XX negative linear regulator datasheet

I have been through the design and implementation of a linear power supply in previous blog posts so I'm not going to repeat myself again.  If people are interested please look at the posts concerning power supplies for how to design linear power supplies.

Here is the schematic diagram:

Linear Dual Power supply for function generator

Here is the PCB layout top and bottom layers:



The circuit is pretty classical in terms of design.  It uses a linear transformer to step down 230V AC to 15V AC.  The 15V AC is then sent to a bridge rectifier which converts the AC voltage into a postive and negative DC voltage.  These DC voltages are then smoothed with two large 2200uF electrolytic capacitors.  Next the voltages are passed through two different coloured LEDS with current limiting resistors - I added the LEDS to show that power was present, they aren't strictly necessary.  Next the positive and negative DC voltages are passed to the respective linear regulators, 7809 (arduino power), 7812 (+12V op amp power) and 7912 (-12V op amp power).

Once I had simulated the circuit to make sure it worked and I hadn't made any stupid mistakes I transferred the designed to a single sided PCB and chemically etched the circuit layout using ferric chloride.  Here is how it turned out:

Top side of the PCB


And finally the PSU running - no load!  I love blue LEDS!

Well...that is about it folks!  The next job will be to design the interface electronics for the signal generator - LCD display and buttons to control the signal generator.  Take care - Langster!