## Saturday, February 23, 2013

### Variable frequency PWM using MikroC + PIC16F887

When I was doing a project on a robot,I found out that the MikroC PWM library doesn’t support variable frequency values for the PWM frequency. I needed to use such variable values to drive servo motor according to the feedback. Hence,I tried to find some other libraries I can use (I know it’s easy to write from scratch,but why show we reinvent the wheel?)

After googling,I found this excellent PWM library for MikroC by Barton J.  Dring.You can get it from his site,Dring Engineering Services PWM page

You just have to include two functions setPWMFreq(...) & setPWMDuty(...) ,from their in your code.Then you can simply call swtPWMFreq(..) function when you need to generate a PWM signal as,

setPWMFreq(unsigned long Fpwm, unsigned long Fosc, unsigned int dutyPercent);

Here I’m going to show how to run a servo motor using PWM,

 include functions setPWMFreq(...) & setPWMDuty(...)  in the beginning void main() { char duty=50; // Set the duty cycle OSCCON=0x10; //Setup Internal Oscillator to 125kHz clock TRISC = 0; //Set portC as output setPWMFreq(9,125000,duty); //Set PWM to 9Hz,Fosc=125kHz,duty=50% while(1){ delay_ms(100); } }

Configuration bits:

Here are some useful pages on PIC PWM

PIC16F887 Datasheet

PWM Calculator

PWM Code

Here is a video of running my servo motors using similar code

PIC18F4550 driving MG995 Servo motors

### Simple 3.3V–5V level shifter

In present day electronic we find many sensors or modules working in 3.3V logic levels.In other terms LVTTL devices (Low-voltage TTL). But even now we mostly use 5V TTL logic level uC or other devices with them. Hence, we need to change logic levels between 3.3V <---> 5V when interfacing both of them together. There are many dedicated chips for this and there was none available in the country. So I decided to build some simple circuits to do this conversion using transistors. Here,you can use any general purpose  NPN transistors available in your country such as 2N39042SC828,BC547…etc. You need to supply 3.3V & 5V as shown in the schematics as Vcc. This won’t be a problem as you may already have these two power rails in your circuit as you use both for chips as Vcc. I have tested this on my 3.3V Bluetooth module interfaced with 5V PIC16F887.It worked well.

### PS/2 Keyboard Interface for PIC uC (PIC16F887)

We need to get various kinds of inputs for our microcontroller circuit. If we need to use key board to input data,we can either use simple buttons or 4x4 keypad…etc. In here I’m going to show you how to use a standard PS/2 computer keyboard for this purpose. It is so cheap and readily available.It is easy to replace a keyboard even for a laymen in an error.

Here I’m using a Mercury branded PS/2 keyboard I got 10 years back.I just cut the cable and got wires directly connected to the circuit.You may find a female PS/2 keyboard socket from ebay or from an old motherboard and use in your projects.

Here is the pinout of a PS/2 keyboard and how i connected to the uC. uC pins are showed in red and the colours of wires on my keyboard are shown in brackets.

Here is the circuit I used to test this.It consists of a 16F887 uC and a simple 16*2 LCD display.You can find additional information on my previous post.

Here is the connection between keyboard and the circuit

I used MikroC built in PS/2 keyboard library for this purpose. You can find more information from here.

I wrote a simple program to display the ASCII value of the pressed key and to show pressed keys in the LCD. You can change the code as you like to get key presses as you wish. The PS/2 library help page is much useful in this.Please note the bolded lines are for keyboard stuff.

 sbit LCD_RS at RB5_bit; sbit LCD_EN at RB4_bit; sbit LCD_D4 at RB3_bit; sbit LCD_D5 at RB2_bit; sbit LCD_D6 at RB1_bit; sbit LCD_D7 at RB0_bit; sbit LCD_RS_Direction at TRISB5_bit; sbit LCD_EN_Direction at TRISB4_bit; sbit LCD_D4_Direction at TRISB3_bit; sbit LCD_D5_Direction at TRISB2_bit; sbit LCD_D6_Direction at TRISB1_bit; sbit LCD_D7_Direction at TRISB0_bit; sbit PS2_Data            at RA7_bit; sbit PS2_Clock           at RA6_bit; sbit PS2_Data_Direction  at TRISA7_bit; sbit PS2_Clock_Direction at TRISA6_bit; unsigned short keydata = 0, special = 0, down = 0; void main() {    char txt[7];     short place=1;     osccon = 0x70;     ansel  = 0;     anselh  = 0;     trisa = 0;     trisb = 0;     trisc = 0;     trisd = 0;     Lcd_Init();     Ps2_Config();   Lcd_Cmd(_LCD_CLEAR);   Lcd_Cmd(_LCD_CURSOR_OFF);   Lcd_Out(1,1,"ASCII:");   for(;;){   portd.f4=1;   delay_ms(10);   portd.f4=0;   delay_ms(10);      if (Ps2_Key_Read(&keydata, &special, &down)) {     IntToStrWithZeros (keydata,txt);     Lcd_Out(1,7,txt);     Lcd_Out(2,place,&keydata);     Lcd_Out(2,place+1," ");     if (place==16){     place=1; }     else{     place=place+1;     }     }   delay_ms(10)   ;   }     }

I used following configuration options for this. Please note I’m using 8Mhz internal oscillator in my projects.

Happy keyboarding!!!!

## Sunday, February 17, 2013

### Step counter for Unipolar stepper motor

In previous post.I told you that I was able to drive an old scavenged unipolar stepper motor from my old printer.As I couldn’t find any datasheet it was not possible to fine how many steps needed for a full turn.I plugged in my 16*2 LCD to the my board and coded a bit to get that measurement.

The circuit and configuration bits are exactly same as the unipolar stepper driver post. The only difference is  plugged the LCD to the connector.

This is the completed circuit.

I marked a small point at the staring point the given time using a marker pen. Using it I can count how many turns it rotated.

Here is the code The bolded lines are used to calculate and show the number of steps

 sbit LCD_RS at RB5_bit; sbit LCD_EN at RB4_bit; sbit LCD_D4 at RB3_bit; sbit LCD_D5 at RB2_bit; sbit LCD_D6 at RB1_bit; sbit LCD_D7 at RB0_bit; sbit LCD_RS_Direction at TRISB5_bit; sbit LCD_EN_Direction at TRISB4_bit; sbit LCD_D4_Direction at TRISB3_bit; sbit LCD_D5_Direction at TRISB2_bit; sbit LCD_D6_Direction at TRISB1_bit; sbit LCD_D7_Direction at TRISB0_bit; void main() { int count=0; char CountStr[7];     osccon = 0x70;     ansel  = 0;     anselh  = 0;     trisa = 0;     trisb = 0;     trisc = 0;     trisd = 0;     Lcd_Init();   Lcd_Cmd(_LCD_CLEAR);   Lcd_Cmd(_LCD_CURSOR_OFF);   Lcd_Out(1,1,"Step Count:");   for(;;){   portd.f4=1;     porta.f7=1;   porta.f6=0;   portc.f0=0;   portc.f1=0;   delay_ms(10);   porta.f7=0;   porta.f6=1;   portc.f0=0;   portc.f1=0;     delay_ms(10);     porta.f7=0;   porta.f6=0;   portc.f0=1;   portc.f1=0;   delay_ms(10);     porta.f7=0;   porta.f6=0;   portc.f0=0;   portc.f1=1;   portd.f4=0;   delay_ms(10);     count=count+1;   IntToStrWithZeros(count, CountStr);   Lcd_Out(2,1,CountStr);   delay_ms(2000)   ;   }     }

I found out that it takes 120 steps to rotate a 360 degree full turn. That is simply 3degrees for a step. Impressive isn’t it ?

### Driving a Unipolar stepper motor using ULN2803 + PIC16F887

Recently I dissembled an old Canon S200SP printer to get some motors. I found a unipolar stepper motor with 5 wires on it. But the model number is unclear as the motor is bit rusted. I tried to give a try.

First thing you have to do it check the resistance between the wires. You will find a wire which has lowest resistance with other wires. This is the centre tap. In my case,it is the red wire and in most cases this wire will be red.

Electronics-diy.com has a good article on stepper motor basics and about windings. I’m not going to tell those again and you can refer to that page.

I simply modified my general ULN2803 driver circuit to drive the stepper motor in single stepping mode (powering up single coil at a time) . I connected stepper motor to ULN2803 as loads according to the 2nd picture.

Now,It is time to do the coding,I simply edited previous MickroC code and same configuration bits were selected The bolded code is for single stepping mode

 void main() {     osccon = 0x70;     ansel  = 0;     anselh  = 0;     trisa = 0;     trisb = 0;     trisc = 0;     trisd = 0;      for(;;){   portd.f4=1;     porta.f7=1;   porta.f6=0;   portc.f0=0;   portc.f1=0;   delay_ms(10);   porta.f7=0;   porta.f6=1;   portc.f0=0;   portc.f1=0;     delay_ms(10);     porta.f7=0;   porta.f6=0;   portc.f0=1;   portc.f1=0;   delay_ms(10);     porta.f7=0;   porta.f6=0;   portc.f0=0;   portc.f1=1;   portd.f4=0;   delay_ms(10);       delay_ms(2000);   }     }

Let’s check the working circuit

If everything is correctly done,Your motor will be in continuous run I’m going to get some angle measurements and to add a LCD to this project. Stay tuned and follow me on twitter @incrediblediy

## Saturday, February 16, 2013

### Driving a DC motor using ULN2803 + PIC16F887

As I showed how to drive external load using ULN2803 coupled to PIC16F887 in the previous post,Here I’m going to drive a small DC motor using that concept

I found this small DC motor from a old CDROM. It was used in the tray eject mechanism of the CDROM.You can find many reusable components by dissembling old electronics such as CDROM,VCR,Printers…etc. As I found it works well even with 5V and draws about 20mA in operation,a nice little motor . The load in the schematic is the motor for this case. I used the same code in the LED driver post and you can get it from there.

The little friend in action

### Driving external loads using ULN2803 with PIC16F887

Here I’m going to drive external loads such as motors,relays,lamps…etc using a Darlington pair setup.The current can be provided by an I/O pin of a uC is not sufficient to drive such large loads.Even if you try to do so,you microcontroller will be damaged.

ULN2803 is a popular Darlington pair IC with 8 Darlington pairs in open collector configuration.Open collector configuration is much useful to drive devices with different voltage requirements than the uC.You can find more information on ULN2803 from its datasheet. I got ULN2803 for around Rs50 (US\$0.4) and it’s easy to use than building from scratch.But please note that output voltage is up to 50V while maximum output collector current is 500mA.  You can also use cheaper ULN2003 but it has only 7 Darlington pairs.

I’m going to build a simple circuit (by modifying the circuit from previous post) as follows to demonstrate the ULN2803’s usage

Here I’m using LED with a series resistor as the load.The Vcc2 is used as +5V too.If you are going to drive motor or other device you have to use the needed voltage for that device as the Vcc2 (12V or so).

Here’s the driving of the led and the MikroC code for it.

Note that bolded lines are use to bling this green LED Configuration bit for the project is same as for the previous post.

 void main() {     osccon = 0x70;     ansel  = 0;     anselh  = 0;     trisa = 0;     trisb = 0;     trisc = 0;     trisd = 0;     for(;;){   portd.f4=1;   porta.f7=1;   delay_ms(5000);   portd.f4=0;   porta.f7=0;   delay_ms(5000);   }     }

### Using PIC16F887 I/O to drive external devices

I’ve done a small addition to circuit on the previous circuit.I’m going to use LCD display I added there,to debug my project too.I’m taking out 6 I/O pins from the PIC16F877 via a connector to the breadboard.

Here is the modification to the previous schematic.

I have written a sample code to check the functionality of the I/O pins by setting them to be ‘0’ logic level.The configuration bits are same as for the previous post. Note that the changes are in bold.

 sbit LCD_RS at RB5_bit; sbit LCD_EN at RB4_bit; sbit LCD_D4 at RB3_bit; sbit LCD_D5 at RB2_bit; sbit LCD_D6 at RB1_bit; sbit LCD_D7 at RB0_bit; sbit LCD_RS_Direction at TRISB5_bit; sbit LCD_EN_Direction at TRISB4_bit; sbit LCD_D4_Direction at TRISB3_bit; sbit LCD_D5_Direction at TRISB2_bit; sbit LCD_D6_Direction at TRISB1_bit; sbit LCD_D7_Direction at TRISB0_bit; void main() {     osccon = 0x70;     ansel  = 0;     anselh  = 0;     trisa = 0;     trisb = 0;     trisc = 0;     trisd = 0;     Lcd_Init();   Lcd_Cmd(_LCD_CLEAR);   Lcd_Cmd(_LCD_CURSOR_OFF);   Lcd_Out(1,1,"www.incredible");   Lcd_Out(2,1,"diy.com");     porta.f7=0;   porta.f6=0;   portc.f0=0;   portc.f1=0;   portc.f2=0;   portc.f3=0;   portd.f0=0;   portd.f1=0;     for(;;){   portd.f4=1;     delay_ms(1000);   portd.f4=0;   delay_ms(1000);   }     }

Here’s how to use the circuit with the breadboard

### Simple 16*2 LCD driver with PIC16F887

In good old days,using a LCD display on a DIY project was quite trouble some.But now it has become much cheaper and simpler to use a LCD in a such project.Here,we are going to use industry defacto Hitachi HD44780 controller base one from ebay.fro US\$ 2.89 including shipping.You can see it here.

Next part is the microcontroller base driver unit.I’m using PIC16F887 as the microcontroller here as I’m going to do some other stuffs with it in upcoming posts . PIC16F887 is really nice uC with internal oscillator upto 8Mhz.So,we don’t have to use external clock source or crystal for non-timing critical application The whole circuit will be simpler to be build and cheaper due to less components.

My choice of programming language is Mikro C Pro as it has many in-built functions.You can get the free demo version as on my previous post.

Let’s look at the schematic diagram

I’m using PicKit2 programmer I built earlier to program the uC using ICSP.The variable resistor connected to VO pin of the LCD is used to change contrast of the LCD.For testing,I’m going to powerup the whole thing using the ICSP port(from +5V via the USB port itself to the PK2 programmer).The LED used for just for monitoring

Let’s look at the MikroC code,

 sbit LCD_RS at RB5_bit; sbit LCD_EN at RB4_bit; sbit LCD_D4 at RB3_bit; sbit LCD_D5 at RB2_bit; sbit LCD_D6 at RB1_bit; sbit LCD_D7 at RB0_bit; sbit LCD_RS_Direction at TRISB5_bit; sbit LCD_EN_Direction at TRISB4_bit; sbit LCD_D4_Direction at TRISB3_bit; sbit LCD_D5_Direction at TRISB2_bit; sbit LCD_D6_Direction at TRISB1_bit; sbit LCD_D7_Direction at TRISB0_bit; void main() {     osccon = 0x70;     ansel  = 0;     anselh  = 0;     trisb = 0;     trisd = 0;     Lcd_Init();   Lcd_Cmd(_LCD_CLEAR);   Lcd_Cmd(_LCD_CURSOR_OFF);   Lcd_Out(1,1,"www.incredible");   Lcd_Out(2,1,"diy.com");     for(;;){   portd.f4=1;   delay_ms(1000);   portd.f4=0;   delay_ms(1000);   }     }

The first few lines are used to define the pins used for the LCD library.You can find more information about that from here.Then,I have set the internal clock to 8Mhz as on the 4.2 section(page 62) of the PIC16F887 datasheet.Check there to find information on how to set different internal clock frequencies other than 8Mhz.Then,ANSEL registered are selected to disable analog input pins(ANx) as I use them as Digital IO pins on my project.The LCD is initialized and Lcd_Out(row,column,”text”) command is used to output characters to the LCD display.Isn’t that so simple (I think the above syntax is self explanatory )

Make sure to select appropriate configuration bits for the project.We have to used oscillator type as internal as below.

Now it is the time to check the built and tested circuit