Mar 20

Getting Started with PIC Microcontrollers–The Timer Peripheral and Interrupts

This time we shall take a look at the timer peripheral; one of the most common peripherals, available on just about every microcontroller. We will also have a brief look at interrupts and how useful they are.

An excellent way of demonstrating both is by revising the original LED blink code in Getting Started with Microcontrollers to make it a lot more efficient.

Here is the original code for reference:

/* 
 * File:   led_blink.c
 * Author: Oli Glaser
 *
 * Created on 02 January 2013, 06:59
 */

// main include file - this contains all the "friendly names"
// for the pins and peripherals
#include <xc.h>
// Turn the Watchdog Timer off
#pragma config WDTE = OFF 

void delay(int d); // This is the prototype declaration for the Delay function

int main(int argc, char** argv) {

    TRISBbits.TRISB6 = 0; // This sets pin RB6 to output

    while(1) // Infinite loop
    {
        PORTBbits.RB6 = 1;  // Set RB6 pin to logic high (5V)
        delay(500);         // Delay for roughly 500ms
        PORTBbits.RB6 = 0;  // Set RB6 pin to logic low (0V)
        delay(500);         // Delay for roughly 500ms
    }

}

// Delay routine
void delay(int d)
{
    int i;  // Declare variable to be used in the loop

    while(d)    // While d > 0
    {
        i = 100;    // set i to 100 for inner loop
        while(i)    // while i > 0
        {
            i--;    // decrement i (e.g. i will equal 99, 98, 97,...)
        }

        d--;    // decrement d
    }
}

So what’s so bad about this code? Two main things:

  1. The timing is not very accurate. Even if we calculate and count the cycles properly (which we don’t do in the above code, it’s just a rough estimate based on observation of the LED) we have to factor in the time taken to execute the instructions for the delay() loop and main while(1) loop, which complicates matters, and depending on the compiler or optimisation settings may vary quite a bit.  

  2. It spends 99% of it’s time doing nothing but counting cycles, which is a “criminal” waste of processor power. While it is doing this, the main loop is tied up and cannot do anything else. In this code that’s not an issue as we are not doing anything else, but imagine if we were – for example using serial communications such as SPI, I2C, UART, etc, and a message arrived during the delay routine; it would almost certainly be missed. Since we spend less than 1% of the time in the main loop the chances of this are very high.

How can we fix these issues?

For the first issue, we could always use the same compiler, make sure it is always set to the same optimisation level, use the tools to count exactly how many instructions are executed in the loops, and adjust the delay routine for this.

For the second issue, if were expecting it, during the delay loop we could poll for incoming data on every cycle of the loop and read/act on it if some arrives. This type of technique is used sometimes but it’s still quite an inefficient way of doing things since we are checking continuously even though no data may arrive for long periods. Every check requires processor cycles, most of which would be redundant and also have to factored into the delay timing.

So we come to interrupts. To clarify the concept with an everyday analogy, imagine you (the processor) have a task which involves switching on and off a signal light (our LED) every couple of hours. You have nothing but a basic clock on the wall. To avoid being late for the switching you would have to continually check the clock to see if it’s time yet (i.e. “polling”)

Now imagine instead of this you have a watch which has an alarm function (the peripheral) which will alert you a couple of minutes beforehand (the interrupt). In this case you have freed up your time to do other things instead of continually checking the wall clock. Now, humans are intelligent enough to have a sense of time so in reality we probably wouldn’t need to check the clock e.g. every minute, and could manage to do other things in the meantime (even so, the alarm system is more efficient even for the human). However a processor is “dumb” and has to check repeatedly until it has a match for its delay setting, so we waste a lot of cycles.    

So if we do things correctly, we should end up with >99% of the processors time free, and <1% taken up servicing the interrupt when it arrives. So let’s take a look at the revised code for our LED blink firmware. When debugging, an easy way to check how much time you are spending in a routine is to set a spare pin high on entry and low on exit – then you can watch it on the scope to see the percentage of time it is high. For multiple routines you can use more than one pin (you can add this into the code below and the previous code to compare the differences in timing – I’ll leave this as an exercise for the reader)

Interrupt based LED blink

/* 
 * File:   led_blink_timer.c
 * Author: Oli Glaser
 *
 * Created on 20 March 2013, 21:31
 */

// main include file - this contains all the "friendly names"
// for the pins and peripherals
#include <xc.h>
// Turn the Watchdog Timer off
#pragma config WDTE = OFF

// Function definitions
void init(void);

int main(int argc, char** argv) {

    // To keep things tidy we put the setup in an initialisation routine this time
    init(); 

    while(1) // Infinite loop
    {
        /* Sit and wait for interrupt!
         * We could be doing other things here
         * in the meantime */
    }
    
}

// Interrupt Service Routine (keyword "interrupt" tells the compiler it's an ISR)
void interrupt int_routine(void)
{
    // Check it's the timer that has interrupted
    if (PIE1bits.TMR1IE && PIR1bits.TMR1IF)
    {
        static char i = 0;
        PIR1bits.TMR1IF = 0;
        T1CONbits.TMR1ON = 0;   // Turn timer off to reset count register
        TMR1H = 0x0B;   // Reset timer count - 0x0BDB = 1Hz
        TMR1L = 0xDB;   //
        T1CONbits.TMR1ON = 1;   // Turn timer back on
        PORTBbits.RB6 = ~PORTBbits.RB6;  // Toggle RB6

    }

    // process other interrupt sources here, if required
}

// Initialisation routine
void init(void)
{
    TRISBbits.TRISB6 = 0;   // This sets pin RB6 to output

    // Setup Timer 1
    T1CON = 0;
    T1CONbits.T1CKPS0 = 1;  // T1CKPS = 11 = 1:8 prescaler
    T1CONbits.T1CKPS1 = 1;  // so timer clock = 1MHz / 8 = 125kHz
    /* Calculating for 1 Hz LED flash, so period needs to be 2Hz as
     * interrupt toggles between on/off. Timer 1 clock is 125kHz, so
     * for 2Hz, we divide 125kHz by 2 = 62,500. Then we subtract this
     * from the rollover value of 65,535, so 65,535 - 62,500 = 3035
     * which is 0x0BDB in hex. Timer 1 has two 8-bit high and low
     * registers, so we put 0x0B in the high and 0xDB in the low */
    TMR1H = 0x0B;           // 65,535 - 62500 = 3035 = 0x0BDB
    TMR1L = 0xDB;           // to count for 0.5 seconds till timer rollover
    T1CONbits.TMR1ON = 1;   // Turn timer on
    INTCONbits.GIE = 1;     // Enable global interrupts
    INTCONbits.PEIE = 1;    // Enable peripheral interrupts
    PIR1bits.TMR1IF = 0;    // Clear Timer 1 interrupt flag
    PIE1bits.TMR1IE = 1;    // Enable Timer 1 interrupt
}

The code is well commented, so hopefully not too much needs to be said about it. I would recommend reading the very detailed Timer 1 section (section 6) thoroughly in the datasheet to get a full idea of what the peripheral is capable of.  If anyone has any questions, just leave a comment.

So how accurate is the timing? Even with the internal RC oscillator it’s just about spot on (for better timing accuracy we would use a crystal oscillator) Here is a scope clip of the results:

Blog - Timer LED Blinkb We can see according to the cursor measurement (in the white box, taken between the two vertical purple dotted lines) it’s 1Hz exactly. The oscilloscope is pretty accurate frequency wise so we can assume it’s very close (it does have a 6 digit frequency counter but this only works for frequencies over 2Hz)

Hopefully this simple introduction has helped to demonstrate the importance of peripherals and interrupts. In future tutorials we will look at combining tasks to get an even better sense of how much more efficient they can make your firmware.

Jan 26

Getting Started with PIC Microcontrollers – The Header File

This time we’ll have an in depth look at a specific area which can present problems for the beginner. Using the simple code presented in Getting Started with Microcontrollers as our example. we will talk a bit about the main xc.h header file, how it works, and how important it is. Understanding this file, and how the registers are mapped to the names we use in the code is very important, will help you form a clearer picture of what is happening behind the scenes, and can save you a lot of debugging time later on. 

Okay, let’s jump right in, here is the previous code for reference:

/* 
 * File:   led_blink.c
 * Author: Oli Glaser
 *
 * Created on 02 January 2013, 06:59
 */

// main include file - this contains all the "friendly names"
// for the pins and peripherals
#include <xc.h>
// Turn the Watchdog Timer off
#pragma config WDTE = OFF 

void delay(int d); // This is the prototype declaration for the Delay function

int main(int argc, char** argv) {
   
    TRISBbits.TRISB6 = 0; // This sets pin RB6 to output
    
    while(1) // Infinite loop
    {
        PORTBbits.RB6 = 1;  // Set RB6 pin to logic high (5V)
        delay(500);         // Delay for roughly 500ms
        PORTBbits.RB6 = 0;  // Set RB6 pin to logic low (0V)
        delay(500);         // Delay for roughly 500ms
    }
    
}

// Delay routine
void delay(int d)
{
    int i;  // Declare variable to be used in the loop

    while(d)    // While d > 0
    {
        i = 100;    // set i to 100 for inner loop
        while(i)    // while i > 0
        {
            i--;    // decrement i (e.g. i will equal 99, 98, 97,...)
        }

        d--;    // decrement d
    }
}

 

Some of you may wonder why the main routine has a return value and argument options, since they are never used in firmware such as this (i.e. the code is executed automatically on power up and never exits) This is simply the default template MPLABX starts you off with when you begin a new project, and conforms to the standard ANSI C entry point. You could also use for example: int main(void) if you wish, but I just leave it as it is.

The main header file

Now for a very important issue, and one which causes many beginners much frustration – the main header file <xc.h>. This header file is a global header that will point to another header file in turn, and eventually point to the header file for the particular part you are using. This contains the friendly names for all the registers (e.g. Ports, Peripherals, etc) in your device, and allows you to type things such as PORTB = 0;

Let’s examine this in detail, and follow the header file “trail” to find out how it does this. To do this, highlight  <xc.h> right click and select Navigate->Go to Declaration as shown below:

MPLABX_GotoImp 

Now, the xc.h file should open in your editor:

#ifndef _XC_H_
#define _XC_H_

#ifdef __XC8
#include <htc.h>
#endif

#endif        //_XC_H

You will notice there is not a lot there, apart from a couple of preprocessor commands, one makes sure that _XC_H_ is defined, and the other includes <htc.h> if __XC8  is defined, which it will be since we are using the XC8 compiler. So let’s follow <htc.h> and see where that leads; use exactly the same method as described above, and you should find this code:

#ifndef _HTC_H_
#define _HTC_H_

#if defined(__CCI__) && !defined(_XC_H_)
#warning "CCI projects should use the top-level support file xc.h\nIncluding xc.h instead"
#include <xc.h>
#endif

/* Definitions for _HTC_EDITION_ values */
#define __LITE__ 0
#define __STD__ 1
#define __PRO__ 2

/* common definitions */

#define    ___mkstr1(x)    #x
#define    ___mkstr(x)    ___mkstr1(x)



/* HI-TECH PICC / PICC-Lite compiler */
#if    defined(__PICC__) || defined(__PICCLITE__)
#include <pic.h>
#endif

/* HI-TECH PICC-18 compiler */
#if    defined(__PICC18__)
#include <pic18.h>
#endif

/* MPLAB C18 Compatibility Header */
#ifdef __18CXX
#include <pic18.h>
#endif

/* HI-TECH dsPICC compiler */
#if    defined(__DSPICC__)
#include <dspic.h>
#endif

/* HI-TECH C for PIC32 */
#if defined(__PICC32__)
#include <pic32.h>
#endif

#endif

Okay, there’s a bit more here, but it still is not the header file we are looking for. Essentially, it is checking to see which compiler is being used and including yet another header based on what it finds. In our case, it is the __PICC__ or __PICC_LITE__ compiler which has already been defined, so we follow <pic.h> (you can tell which code is being used as the unused code will be greyed out, whilst the <pic.h> should be highlighted). Now we get to another file which includes <pic_chip_select.h> and <eeprom_routines.h>. Follow the <pic_chip_select.h>  header, and we are finally getting somewhere – this is a huge file that checks for the particular part you are using (defined automatically when you select the part during project setup) and includes the header that contains all the important definitions mentioned at the start. Depending on your part, you will see one of the related sections highlighted. I used the PIC16F690 for the first tutorial, so scanning the file, about halfway down I come across this highlighted code:

PIC_Include  

Now if we look in pic16f690.h (or whatever the header file for you part is), we will see a very long list of defintions which map the addresses of the registers to the “friendly names” we use in our code. Since we used PORTB in our code, lets take a look at the definition for this in the file:

// Register: PORTB
extern volatile unsigned char           PORTB               @ 0x006;
#ifndef _LIB_BUILD
asm("PORTB equ 06h");
#endif
// bitfield definitions
typedef union {
    struct {
        unsigned                        :4;
        unsigned RB4                    :1;
        unsigned RB5                    :1;
        unsigned RB6                    :1;
        unsigned RB7                    :1;
    };
} PORTBbits_t;
extern volatile PORTBbits_t PORTBbits @ 0x006;
// bitfield macros
#define _PORTB_RB4_POSN                                     0x4
#define _PORTB_RB4_POSITION                                 0x4
#define _PORTB_RB4_SIZE                                     0x1
#define _PORTB_RB4_LENGTH                                   0x1
#define _PORTB_RB4_MASK                                     0x10
#define _PORTB_RB5_POSN                                     0x5
#define _PORTB_RB5_POSITION                                 0x5
#define _PORTB_RB5_SIZE                                     0x1
#define _PORTB_RB5_LENGTH                                   0x1
#define _PORTB_RB5_MASK                                     0x20
#define _PORTB_RB6_POSN                                     0x6
#define _PORTB_RB6_POSITION                                 0x6
#define _PORTB_RB6_SIZE                                     0x1
#define _PORTB_RB6_LENGTH                                   0x1
#define _PORTB_RB6_MASK                                     0x40
#define _PORTB_RB7_POSN                                     0x7
#define _PORTB_RB7_POSITION                                 0x7
#define _PORTB_RB7_SIZE                                     0x1
#define _PORTB_RB7_LENGTH                                   0x1
#define _PORTB_RB7_MASK                                     0x80

Now we can see how it works. Don’t worry if you don’t fully understand it, you don’t need to in order to use it, but it helps to know where these definitions are and why the compiler will complain if it can’t find them. For further reading check the XC8 Compiler User’s Guide (this will also be on your computer under the Microchip->MPLAB XC8 folder). We won’t fully cover all the above code (General C books, PIC specific C books, and the users guide mentioned cover all this), apart from the most important part of it:

// Register: PORTB
extern volatile unsigned char           PORTB               @ 0x006;

Note the @ 0×006; part of this code. This points the PORTB declaration to a specific address in the microcontrollers memory. If we check the PIC16F690 datasheet and look at page 31, we will see a table of the Special Function Registers and their addresses:

PIC16F690Registers

Note that PORTB is at address 06h, as defined in the header file. If you check the other registers you will see they will all correspond with the datasheet table.

Hopefully the above has helped to show how important the main header file is, and how the code connects with the hardware. This brings us on to the last part of this tutorial; making sure your tools know where to look for the header file. Firstly, click on the spanner icon in the “Dashboard” at the bottom left hand of your screen. This brings up the Project Properties dialog box. Select compiler properties, pre-processing and messages in the dropdown and in the include directories box, you need to point to the folder which contains the compiler include files:

IncludeDir

Usually it’s under something like C:\Program Files\Microchip\xc8\v1.12\include as shown in the clip, but it may be different if for example, you chose another install directory or Microchip decides to rearrange things in the near future.

Jan 04

Getting Started with PIC Microcontrollers


 

How to get started with microcontrollers is a very common question, and can be quite daunting for the newcomer. We will start right from the beginning, assuming almost no prior knowledge of the subject. Although we will probably cover other micros in later tutorials, we will start with the very popular PIC microcontroller range from Microchip.

What tools do I need to get started?

Luckily the answer to this question is “not very much”. At the minimum you will need:

  • A means of programming your microcontroller with the code you have written (generally known as “firmware”) There are hundreds of programmers to choose from out there, ranging from cheap “hobbyist type” to very expensive production programmers. For me, an important feature of the programmer is the ability to debug your code, and be able to be driven from within MPLAB or MPLABX – these are Microchips Integrated Development Environments (IDEs – we will cover these shortly)  Personally, I recommend either the PICkit3 or the ICD3, as these are the two I have experience with. Both have the features mentioned above, the only difference is that the ICD3 does a little more on the debugging side, programs faster and is a  “production programmer”. The is a comparison of their relative features here. If you don’t know what to start with, I’d go for the PICkit3.
  • A tool with which to organise your projects and write your code (an IDE) Microchip provides MPLAB and MPLABX for this purpose. MPLAB was the only IDE from Microchip for a long time, but recently MPLABX has been released and is the new IDE Microchip are focusing on. It’s based on Netbeans, and you get a feature packed tool somewhat like Eclipse/Visual Studio. I would pick MPLABX here, as it has many more features, plus MPLAB will probably be discontinued at some future point. If you are going to follow this tutorial right through to the end, then now would be good time to start downloading and installing MPLABX, and the XC8 compiler (free version – in the left column of the linked page) whilst you are reading the rest. Don’t worry if you have no components yet, if you wish you can use the simulator to run the code presented later on. For this all you need is your computer.
  • Something to test your microcontroller with. This could be a Development Board, or simply a breadboard you can layout yourself. On the dev board side, at $70 the PICkit3 starter kit is a pretty good choice; it’s on this page along with other starter kits. It comes with everything you need to get started, plus some tutorials on basic assembly programming. Olimex and other independent vendors also make some good dev boards. On the breadboard side, it’s a little more complex but more versatile, plus you will probably learn more this way. Which you choose depends on how much of a challenge you feel up to. We will cover the breadboard option here, but the discussion of coding and firmware will be just as relevant whichever option you take.
  • Optional – some prior knowledge of programming or electronics – particularly the C language as this is the language of choice for small micros. Assembler is well worth looking at, but nowadays memory is cheap, micros are fast and making firmware as small and efficient as possible is no longer as important as it used to be (many folk will disagree with this, and you will frequently see Assembly vs C discussions – my view is learn C for 99% of your firmware and use inline assembly when you need to, since they can be used together)

The breadboard route

First you need a breadboard (read link for how they work) and a few components to go with your microcontroller. A breadboard is used to make circuits up quickly and conveniently during prototyping. They all look something like this:

Secondly you need your PIC, and a few components to plug into it. For the PIC, we will choose something from the 16F series. Depending on what you can get hold of, this can be pretty much anything from that range. This is a common problem for newcomers, when they see a circuit on the ‘net which uses e.g. a PIC16F628, they assume that only that part will do. This is not the case – often, all that is involved in using code written for one PIC with another PIC is simply changing a couple of lines of code. Even jumping from say, the 16F series to the 18F/24F/32F series is not too difficult – this is the beauty of the C language: your code is portable, so you don’t have to write the same routine for each different microcontroller (this is one big advantage over using assembly)

I realise it can be difficult to get the newest parts in certain places, so here we will pick the PIC16F690, an oldish but reasonable part that should be widely available. If not, pick something similar – ideally source from places like Mouser, Digikey, Farnell, RS, etc; they have the latest stuff in stock at better prices than the smaller vendors. The downside is there is usually a minimum order for free delivery, but if you plan things you can order a few weeks worth of parts at once. I will mainly link to parts from Farnell here as that is my main source of components, but obviously you can get the same parts from many different places (eBay is good for cheap and cheerful parts, just watch out for dodgy vendors)

Anyway, here is a basic list of parts to start with (many of these are available in kits such as this one, so shop around a bit):

  • Breadboard – preferably select a decent size one with power tie points as shown above.
  • A load of jumper wires to connect your circuit together with. You can either buy some ready made ones such as these or these, or buy a roll of single core wire (I use 0.6mm which is equivalent to ~22.5AWG, but 22AWG or 20AWG should do fine) and cut your own.
  • A header to plug your programmer into during programing/debugging – this depends on which programmer you have. For the PICkit3 you need a simple 6-pin 2.54mm pitch header, whilst for an ICD3 you need either an RJ-11 (6-pin type), an RJ11 to 6-pin header adapter or this very convenient breadboard cable adapter.
  • Some passive components (“passive” roughly means things that don’t require power to perform their function, like resistors, capacitors, inductors)
  • Capacitors – 20 x 100nF ceramic capacitors (also listed as 0.1uF, which is the same value, 1nF is 1/1000th of a uF) – you will use a lot of these. 10pF, 15pF and 22pF ceramic (here are some options). 10uF, 100uF, 220uF, 470uF electrolytic types. There are also starter kits available which combine many of the common values.
  • Resistors – 10Ω, 47Ω, 220Ω, 1kΩ, 2.2kΩ, 10kΩ, 22kΩ, 47kΩ, 100kΩ, 470kΩ, 1MΩ metal film or carbon film type should be enough to get you started (or you can buy a kit of various standard values such as this, though you can often pay a lot more for the convenience of having them selected for you)
  • Crystals – the modern PICs have an internal oscillator (this is the thing that supplies the clock to the internal circuit) but it’s not as accurate timing wise as using an external crystal. Some applications require accurate timing, such as serial communications (e.g. RS232 or USB between PIC and PC) so you may want to grab some of these. Typical handy values are 32.768kHz, 4MHz, 8MHz, 12MHz, 20MHz.
  • LEDs – you need something to indicate events, an LED is a cheap and simple way of doing this. They come in many colours, shapes and sizes, but start off with some simple 5mm red LEDs.
  • General purpose transistors – you will need these for various things along the way, often for driving things that the PIC pins don’t have enough power to handle. There are two main types of transistor, bipolar and FET (Field Effect Transistor) Both have their uses. The choice of parts is overwhelming – some BC337-40 NPN, BC327 PNP, and some BS270 N-ch MOSFETs are a good start.
  • 7-segment displays, LCDs, Buzzers, Sensors, Motors – the list is endless once you get past the basics. Again, there are sensor kits available from places like Sparkfun, Adafruit, and other vendors if you want a basic selection handy for future use.

Okay, assuming you have (at least some of) the basic parts above, how do you wire things up on your breadboard? This is where the vendors datasheets and application notes (“app notes”) come in handy (you should read your first microcontroller datasheet from start to finish – all the information you need is there)

The datasheet, or a related app note will often have a minimum operational diagram. Googling a bit for things like (“PIC schematic”, “PIC16F starter kit schematic”, etc) brings up plenty of useful info. Using the “images” search option is often a good way to find what you are looking for.

Anyway, at the end of the “Low Pin Count Demo Board” app note, we find a very simple schematic, I have snipped out the relevant part of it below and taken the liberty of simplifying it a bit:

PIC16F690 Setup 2

We can see it’s very basic, apart from the PIC16F690 (U1) itself, there is only R1, C1 and P1 in addition. R1 is a 10kΩ resistor mentioned above, C1 is one of the 100nF ceramic capacitors (marked as 0.1uF – get used to this different marking of what is actually the same value, it happens all the time), and P1 is the 6-pin 2.54mm pitch header also mentioned. SW1 is optional, this can be used to reset the microcontroller, but if you have the programmer connected you can do this from within MPLAB (or disable the reset function entirely)

If you are not used to reading schematics, all the symbols marked the same are physically connected to each other (this saves making things messy by having to draw wires everywhere) For example, the little arrow with V+ above it is connected to all the other V+ symbols (V+ is your supply voltage, typically +5V for this PIC which can be supplied from your PICkit3 or ICD3 – not all programmers have this option though). Also the little downwards pointing triangle made from three horizontal lines means circuit ground, and these points are all connected together. Same again with the symbol marked RA3, the point over on the right is connected to pin 4 of the microcontroller which has the same symbol attached to it. 

Breadboarding the circuit

Okay, enough waffle, let’s actually make something happen. Since, we don’t have any display, the standard “Hello world” equivalent for microcontrollers is the LED blinking project, so we’ll go for this (boring I know, but it’s a start…)

This is the same schematic as the previous one (it’s good to get used to seeing schematics in different formats), but we have added a couple of LEDs and resistors in for blinking purposes.

1_LED

Now to setup the circuit on the breadboard, here is the result:

Breadboard_Layout2_Annotated3

Ignore the yellow capacitor at the right middle (it’s part of another circuit on the same board) You can see the 100nF capacitor across the power pins, the anode of the LED connected to RB6, it’s cathode connected to the resistor then the resistor connects to the circuit ground at the top (pin 20 of the microcontroller) Also you can see the 10kΩ resistor between MCLR (pin 4) and the positive supply pin (Vcc – pin 1) The wires plugged into the board are the adapter wires from the ICD3 breadboard cable adapter previously mentioned above.

Creating the project in MPLABX

Okay, now everything is setup, it’s time to write the code. Open up MPLABX and click on File->New Project (or Ctrl-Shift-N) This will bring up the following dialog box:

MPLABX_New_Project

Select Standalone Project and click next. You will be presented with the dialog box below.We now need to select the part we will be using, so select Mid Range 8-bit MCUs and PIC16F690 (or if you are using another similar part 20-pin like the PIC16F685, PIC16F687, PIC16F689, etc, then select this instead) and click next.

MPLABX_New_Project_Select_Micro

You will now be asked to select an optional debug header (these parts do not have on chip debug capabilities) which we won’t be using, so just click next.

Now we get a dialog asking to select a tool for programming (e.g. a PICkit3, ICD3, etc) I have my ICD3 plugged in so I have selected this. Select your tool and click next.

MPLABX_New_Project_Select_Programmer

Now we have to select the compiler we will be using, so we choose the XC8 compiler we downloaded before (if you didn’t, here’s the compiler page link again) You may have other compilers installed (as you can see I have) so make sure the XC8 compiler is highlighted and click next.

MPLABX_New_Project_Compiler

Now we finally give the project a name – I named it “LED Blink” and put it in a folder of the same name. Select “Set as main project” also (this just means it will be the active one of you have more than one project in your workspace) and click Finish:

MPLABX_New_Project_Name

Writing the code

Okay, we’re finally done setting up the project, now we can write the code. Under the “Projects” tab, right click on “Source Files” and select “C Main File”. This will create a basic template main file for you. You can rename it if you like from the default “newmain”, I called it “led_blink”.

MPLABX_Add_Source

You should now have something like this in the editor:

MPLABX_Source

Don’t worry if you don’t understand the code, we will cover that in future tutorials. For now, let’s just get the LED blinking. Basically, all we need to add is a loop with two instructions to send a logic 1 to the LED pin, with a delay between them. Here is the updated code with this added:

/* 
 * File:   led_blink.c
 * Author: Oli Glaser
 *
 * Created on 02 January 2013, 06:59
 */

// main include file - this contains all the "friendly names"
// for the pins and peripherals
#include <xc.h>
// Turn the Watchdog Timer off
#pragma config WDTE = OFF 

void delay(int d); // This is the prototype declaration for the Delay function

int main(int argc, char** argv) {

    TRISBbits.TRISB6 = 0; // This sets pin RB6 to output

    while(1) // Infinite loop
    {
        PORTBbits.RB6 = 1;  // Set RB6 pin to logic high (5V)
        delay(500);         // Delay for roughly 500ms
        PORTBbits.RB6 = 0;  // Set RB6 pin to logic low (0V)
        delay(500);         // Delay for roughly 500ms
    }

}

// Delay routine
void delay(int d)
{
    int i;  // Declare variable to be used in the loop

    while(d)    // While d > 0
    {
        i = 100;    // set i to 100 for inner loop
        while(i)    // while i > 0
        {
            i--;    // decrement i (e.g. i will equal 99, 98, 97,...)
        }

        d--;    // decrement d
    }
}

And that’s it, just copy the above code and replace the entire contents of the file with it. You will notice we changed the intial header files (e.g. #include stdio.h and stlib.h) and added #include <xc.h>. We also added a rather important line, the #pragma WDTE = OFF – this turns the watchdog timer off. The watchdog timer is a timer that needs to be reset before it times out otherwise it will reset your microcontroller. This can be useful in case the microcontroller hangs for whatever reason, but we don’t need it here as it adds complications.

We will cover more on these features in future tutorials. For now, you can experiment with the timing of the LED blink by passing different values to the delay routine. You could also try adding another LED to RB7 (hint – you need to make sure the pin is set to output)

I hope this is of use to a few people. If you spotted any mistakes, have any questions, ideas for improvement, suggestions for future tutorials, then leave a comment and I’ll do my best to answer promptly.

Jun 13

Mole Deterrent Teardown

Having a very healthy population of moles in our vicinity, I logged onto eBay and bought four of the cheaply available (ultra?)sonic mole deterrents for our garden lawns in the hope of persuading them to move elsewhere. Here’s a link to a couple of similar ads: eBay ad, eBay ad2.

MoleRepllerPic

The basic idea is pretty simple and used with other animals too – the gadget emits an frequency that the animals in question (in this case the moles) aren’t keen on, so they move away from the area. Some are advertised as being “ultrasonic mole deterrent”, and some simply say “sonic mole deterrent”.

A few questions spring to mind:

  1. Do they actually work?
  2. Are they sonic or ultrasonic? (ultrasonic means above the range of human hearing  of which the upper limit is around 20kHz) What frequency do they actually work at?
  3. What’s the build quality like? How long are they likely to function properly for?

Do they work?

Unfortunately the particular model purchased didn’t work for long enough (see below) to answer this question fully, but I’d say they did seem to make a difference initially. Further tests will have to be made on this front..

I took a look inside one to try and answer the second and third questions, see how it operates and whether any “improvements” might be made.

Here’s a picture of the various bits:

20120526_155710

We have 2 x 1.2V 600mAh NiMH batteries, a solar panel, a buzzer of some sort and a little circuit board.

Here’s a close up of the circuit board:

20120526_155820

Tracing out the circuit in LTSpice (an excellent free SPICE simulator) produced this schematic:

Mole Repeller Circuit

Note that 2N2222 and 2N907 are used in the SPICE circuit as LTSpice doesn’t have models for 9014 or S8550, which are the actual parts used on the PCB. This matters little to the simulation (see below) as the circuit should work fine with most “general purpose” bipolar transistors.

The function of the circuit is very simple – to briefly turn on the buzzer every 20 or so seconds. Here is a run through of the operation:

Q1 and Q3 are responsible for the on/off pulses. If we start with Q1 turned on (via current through R1 into base), Q3 turned off, and either side of C1 at around 0V. R7 gradually charges up the right side of C1 (Q3b) until the voltage reaches around 500mV at which point Q3 will begin to turn on. When Q3 starts to turn on, Q4 and Q2 (BUZ_V) will also begin to turn on, activating the buzzer. Also the bottom of C2 will be pulled to ground, which will also pull Q1s base (Q1b) low, turning it off – this will raise the voltage on the left (Q1c) and right side of C1, accelerating Q3s turn on. Things will stay like this for around 1 second until C2 charges up through R1 and the base of Q1 (Q1b) reaches ~500mV, at which point Q1 will turn on and  C1 will be pulled low, pulling the base of Q3 to ground and turning Q4 and Q2 (and the buzzer) off again. Then the process repeats….

If we run the simulation of the above circuit in LTSpice we get these waveforms (waveform names below correspond to bracketed names in the description and labels in the schematic above):

Mole Repeller Simulation 3

So, how accurate is the simulation? Pretty accurate as it turns out – here are the waveforms for Q1c (yellow) and Q3b (red) over 30 seconds, we can see they are almost identical to the simulation:

20120613_915639

What frequency does the buzzer run at?

To answer this question and find out how the buzzer operates, I pulled the casing apart and took a look inside:

20120612_000241

It’s a very simple construction, consisting of one resistor, a transistor of some sort, a magnet on an arm and a coil with two windings to produce what is called a “blocking oscillator”. The electromagnetic coil produces an oscillating magnetic field which makes the magnet arm vibrate against a diaphragm producing the sound.

Here is a schematic:

Buzzer

Some guesswork has been applied here as the (unmarked) transistor has 4 pins, not the usual 3. I think there may be a diode (represented by D2, possibly for temperature compensation) included in the package with it’s cathode connected to ground, so pin 4 would be the anode of D2.  The part numbers 1N4148 and BC847C are not the real part numbers, just a random diode and NPN from the LTSpice library.  The coil inductance values are guessed at too, but the resistor is definitely a 1.5k part.

This is not the most common blocking oscillator topology, with the control coil from base to ground (via biasing/compensating diode) rather than from supply to base (see below joule thief example) For further reading, Wiki has good pages on the blocking oscillator, and also the popular Joule Thief which utilises such an oscillator:

For the version I think is used in our buzzer I managed to track down a buzzer patent 4,065,733 which describes the use of a diode subject to the same thermal changes (e.g. ideally part of the same IC) as a compensating bias element.

The links above all have explanations of operation, but here is rough run through. If we begin with Q1 turned on, L_DRIVE_COIL begins to charge. Since it is coupled to L_CONTROL_COIL, the changing current induces a voltage across L_CONTROL_COIL keeping Q1 turned on. As the magnetising current slope levels out on L_DRIVE_COIL, the induced voltage into L_CONTROL_COIL drops. This lowers the voltage across L_CONTROL_COIL, stealing base current and begins to turn Q1 off. As Q1 turns off, L_DRIVE_COIL attempts to keep the current flowing and a voltage of the opposite polarity appears across it. Since it is coupled with L_CONTROL_COIL this accelerates the turn off process, with a voltage of the opposite polarity appearing across L_CONTROL_COIL bringing the base voltage below 0V. Q1 remains turned off until L_DRIVE_COIL discharges (i.e. “blocked”, hence the name) and the voltage on L_CONTROL_COIL drops, allowing the transistor to begin to turn on again.

To answer the frequency question, a quick test with the scope found out it runs at 359 Hz:

20120613_920124

So, it’s not ultrasonic. My suspicion is that they all work around the same frequency (300-1000Hz) but some advertise as ultrasonic, presumably being unaware of the meaning (or maybe as they think it sounds better) Some ads (such as this one) advertise ultrasonic, but then state an operating frequency of 400-1000Hz in the specs, which seems to support this theory. The low frequency is apparently meant to simulate the sound of other moles burrowing. This makes more sense to me than an ultrasonic frequency for repelling moles, but I couldn’t find much data on what frequencies work best, or the hearing range of the mole.

What about the quality?

To put it simply, the quality of this product is pretty terrible. They are not built to withstand continuous operation outdoors. Reasonable proof of this was the fact that out of the 4 purchased, within a few months of use outside, all 4 were no longer working. So what went wrong?

Although there is nothing wrong with the principle of the buzzer operation, unfortunately the actual design of the buzzers in this product is not up to scratch. 3 out of the 4 failed due to the permanent magnet on the end of the armature coming loose as can be seen below (note the magnet is separated from the arm and lying on the white sealant stuff):

20120612_081032

On inspection, it was found that the magnet is simply glued on with what appears to be something like super glue. This is simply not going to stand repeated vibration for long. Another issue is that the enclosure is not well sealed and none of the circuitry is “weatherproofed” (e.g. conformal coating or potting) This fact caused the remaining one to fail:

20120614_081730

20120614_081452

Next time we’ll have a look at designing a better version Winking smile