Thursday, September 6, 2012

Driving Motors

I dug out a couple of small motors to try to drive. I have a 4 channel motor driver, L293D too. Micro controllers (MCU) cannot power a motor directly, the motor draws far too much current and would quickly destroy a micro controller in a puff of acrid smoke. Some sort of interface is needed that is controlled by the output of a MCU and switches the current needed by a motor. Motors come in a variety of voltages too, again the interface could handle this. There are a few options for the interface. One is to build your own using transistors to handle the difference in current and voltage but another is to use a dedicated chip, such as the L293D.

The L393D allows 2 motors to be connected, which can operate at up to 36V. They can each draw up to 600mA, which is not very much. There are motor drivers available that handle much bigger currents, but 600mA should do for now. The controller allows the motor to be driven in either direction too, which is useful.

The L293D has three control connections for each motor: enable, A and B. Enable lets the motor run, so if it is low the motor will not run. A and B determine the way the motor turns, if A or B is high and the other is low the motor will run in one direction depending which is high and which way round the motor is connected. If A and B are both low or both high the motor is braked to a halt, whereas if enable is made low when A or B (not both) is high then the motor coasts to a halt.

The chip has two supply pins, one logic supply should be the same as the micro controller and one to supply the motors. Keeping the two supplies separate is important, not only to prevent damage to the micro controller, but also because motors are very electrically noisy beasts. Some capacitors are often required across the motor connections to smooth out the spikes.

The L293D can respond to switching on and off at up to about 5kHz. If the enable pin is switched on and off quickly this will give the motor bursts of power with coasting in between. By varying the length of the pulse and the pause in between the speed the motor runs at can be controlled. This is ideal for Pulse Width Modulation from a MCU.

Wednesday, August 29, 2012

Hello World for PIC

When testing out a new programming language the simplest program is to write out "Hello World". Making an LED light when a switch is closed must be similar for a micro controller. My first foray into PIC coding in C was to respond to three switches with three LEDs and it worked well. What I'm impressed by is the simplicity of the code and how easy it was to put that code into the PIC ready for use.

The code is here:

/*************************************************
 * Description: switch on LEDs with switches
 *
 * File: switches.c
 * Author: Chris Hill
 * Created: August 2012
 *
 ************************************************/

#include
#include

__CONFIG(FOSC_XT & WDTE_OFF & PWRTE_ON & CP_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & WRT_ON);

/***** GLOBAL VARIABLES *****/
union {
    uint8_t port;
    struct {
        unsigned RB0 : 1;
        unsigned RB1 : 1;
        unsigned RB2 : 1;
        unsigned RB3 : 1;
        unsigned RB4 : 1;
        unsigned RB5 : 1;
        unsigned RB6 : 1;
        unsigned RB7 : 1;
        };
    } sPORTB;


#define SW1 PORTBbits.RB7
#define SW2 PORTBbits.RB6
#define SW3 PORTBbits.RB5

#define sLED1 sPORTB.RB2
#define sLED2 sPORTB.RB1
#define sLED3 sPORTB.RB0

void main() {

    // initialisation
    TRISB = 0b11111000;

    for (;;) {
        sLED1 = SW1 ? 1 : 0;
        sLED2 = SW2 ? 1 : 0;
        sLED3 = SW3 ? 1 : 0;

        PORTB=sPORTB.port;
    }
}



It looks quite long at first sight, but it is simple enough, most of the complexity coming from a union to create a shadow for PORTB. This allows the shadow PORTB to be addressed as an eight bit integer or as individual bits. I like to use the shadow for ports because it helps with the read-modify-write problem of I/O ports. There no need to debounce the switches, the LEDs would just flash so fast that no one would notice.

The compiler makes accessing registers in various banks much easier, such as TRISB, makes everything a bit more readable and so less prone to errors - though perhaps professional assembler programmers might not agree. The resulting code is 47 words long out of 4096 available in the PIC16F873, so room to grow.

The hardware layout to test this was set up on bread board, rather randomly set up as a temporary test. I used an external crystal - I usually do - so I needed to connect two 33pF capacitors between GND and the crystal and pins 8 & 9, hook up +5v to pin 20, two GND pins 8 & 19 and connect the MCLR (pin 1) to +5v. You need this for every circuit so it it easy enough to leave it on a bread board ready for the next circuit. This is not quite as plug and go as an Arduino, but not too hard either. If I build something I want to make more permanent then something on Veroboard is easy to make too.

Overall I think the PicKit 3 and the XC8 C compiler from Microchip has encouraged me to dabble again micro controller electronics. So what next?

Monday, August 27, 2012

PicKit 3

I've had a long lay off from electronics, but the bug has bitten again. I wanted to drive some small motors at variable speeds. The way I would have tried in the past would have been to try using pulse width modulation from a Microchip PIC pin to create the pulses to drive a motor. The motor draws too much current to drive directly from a PIC pin, but a transistor or a half bridge would be fine, either using the PIC pin to control the motor.

I dug out the PIC chips I could find and looked on-line for datasheets etc. I found some PIC16F873 chips - t'Interweb informs me that these are out-of-date, but I thought I'd have a go anyway.

In the past I would have used Microchip's MPLAB to create the code for the PIC chip. The code would have been PIC assembler for their mid-range chips. I would then have copied the compiled code (as a hex file) to a program supplied by Velleman that used their K8084 PIC programmer to write it out to the chip. I never used the assembler enough to get properly familiar with it, so it was always an error-prone struggle that put me off a bit. All of this software expected to run on Windows which I am very happy to have moved away from onto Linux, so there is a another problem. Lastly the Velleman board connects with a serial cable (not USB) and it seems that a USB to Serial converter does not work with it.

I have since discovered Arduino. It uses USB, can be powered by the USB, has a C compiler that run in an IDE on Linux and works very well. Uploading the code to the Arduino is simple via the USB connection and the serial connection allows communication between the PC and the board. Arduino is easy to use and seems very popular, it does seem to be a bit of a one-size-fit-all. The chip usually comes pre-installed on a board with the external connections presented around the edges. Arduino is more expensive than a PIC and there are hundreds of PIC devices to choose from. I think the idea of using a PIC and Arduino in suitable places seems interesting too.

While I was looking at all of this I noticed that Microchip have ditched their in-house development platform and moved to Netbeans. This is an IDE I have used before. It works well so I thought I'd try it out. A download and install later and I could now assemble PIC code on my Linux PC, so the first Windows hurdle was overcome. Then I discovered that the Velleman PIC programmer didn't work - I think some of my soldering of the kit has let go. I looked for what the modern way of programming PICs (even my old ones) would be and discovered PicKit3. It is a programmer and debugger from Microchip which integrates nicely with the new Netbeans IDE, which they now call MPLabX. I found also that there are clones of PicKit 3 available so I ordered one from a Chinese company. It came with a Zero Insertion Force board for a range of chip sizes to plug into the PicKit 3 so plain PIC chips can be programmed.

So all that remained was to find a C compiler for PIC chips. As I looked through the literature on-line I discovered that Microchip have just released a new compiler called XC-8 for the mid-range PIC chips, like mine. The basic option is free. I have just downloaded it and installed it on my laptop into MPLabX, so now I need to try it.

Thursday, January 7, 2010

Lost volts

I have a a battery case that holds 6 'C' size batteries.  When charged, six batteries would deliver more than 6 volts for a couple of little motors I have.  I didn't have a C size case for four batteries so I took two batteries out and put packers in.  When checked the voltage it was only 4.5v.  After scratching my head I took the packers out and fiddled with them thinking there was a problem with their contacts. Eventually I checked the voltage of all six batteries out of the case and then in the case and found a 1.1v drop.  It turns out that a contact in the case had corroded and that was the problem.

So if you use a battery case check that it hasn't corroded so it doesn't add resistance you don't want.

Monday, December 28, 2009

Byte vs int

I've just checked the difference between declaring pin numbers as byte or int.  There is no difference to the size of the compiled code, so there is not likely to be a performance difference.  Since it probably saves one byte per constant I'll try to use byte not int.

Now the code

I created a simple piece of code to test the schematic and my understanding of the way things work, which is below.  The best thing about Arduino is that the code is C, not assembler.  I have been reading the examples and the reference stuff on the web site  then I wrote the code below in one go.  It worked first time after only one failed compile for a missing semicolon.  In PIC assembler the chance of me writing code like that and getting it to work at the first attempt is zero. 

There are four sections to the code.  The first is the declarations section and defines the names of the pins to use.  The second is the setup routine, that is stuff that only happens once.  The third section is the loop which repeats for ever while there is power.  Lastly there are subroutines.

In the declarations I use const for pin names because they won't change.  I use int because all of the examples do, but really I feel we should use byte.  byte is only one byte, (int is two) and byte can only be positive.  These suit the pins perfectly and would save one byte per pin - a few bytes might be important on these small controllers, but not in this case.  There could be a down side if conversions take place - I'll experiment later.  Setup includes a call to a routine which blinks the on-board LED.  If the board resets for any reason the blinks will give it away.

The loop sets up the motor in one direction and steps up the speed to full speed in the for loop.  It then stops the motor, giving it time to stop, reverses the motor and steps it up to full speed again.  Then it stops the motor before the loop repeats.

The subroutines only have the blink routine, used to blink the on-board LED.

const int mot1Pin = 7;
const int mot2Pin = 8;
const int enablePin = 9;
const int ledPin =  13;

void setup() {
  pinMode(mot1Pin,OUTPUT);
  pinMode(mot2Pin,OUTPUT);
  pinMode(enablePin,OUTPUT);
  pinMode(ledPin, OUTPUT);

  //demonstrate a reset by flashing the led
  blink(ledPin,3,300);
 
  //disable the motor
  digitalWrite(enablePin, LOW);
}

void loop()
{
  // simple test to change a motor speed bit by bit
 
  // first set the motor in one direction
  digitalWrite(mot1Pin, LOW);
  digitalWrite(mot2Pin, HIGH);
 
  //run the motor in stages up to full speed
  for ( int i=0;i<255; i+=60) {
    analogWrite(enablePin, i);
    delay(1000);
  }
  analogWrite(enablePin, 255);
  delay(1000);
 
  //stop the motor
  analogWrite(enablePin, 0);
  digitalWrite(mot1Pin, LOW);
  digitalWrite(mot2Pin, LOW);
 
  // pause to allow stop
  delay(2000);
 
  //reverse
  digitalWrite(mot1Pin, HIGH);
  digitalWrite(mot2Pin, LOW);
 
  //run the motor in stages up to full speed
  for ( int i=0;i<255; i+=60) {
    analogWrite(enablePin, i);
    delay(1000);
  }
  analogWrite(enablePin, 255);
  delay(1000);
 
  //stop the motor
  analogWrite(enablePin, 0);
  digitalWrite(mot1Pin, LOW);
  digitalWrite(mot2Pin, LOW);
 
  // pause to allow stop
  delay(2000);
}

// blink an LED
void blink(int pin, int num, int pause) {
  int p=pause/2;
  for ( int i=0;i
    digitalWrite(pin, HIGH);
    delay(p);
    digitalWrite(pin, LOW);
    delay(p);
  }
}

Saturday, December 26, 2009

Schematic





Working from a diagram helps when you're building something, but what if you don't have one?  No problem, create your own.  I have just had a go with Cadsoft Eagle and produced a schematic for driving a motor from an Arduino board. I don't think my design standards are too good, but it does the job.  There wasn't a schematic for a motor in the library, but since the software is aimed at creating a board and motors are not usually soldered to a PCB that probably makes sense.

If you're thinking of using this schematic, and you are free to do so, then I suggest you wait until I've built it and tested it.  The next stage is to write the software.