Monday, August 5, 2013

Schematic and DesignSpark review


After getting the breadboard version of pennybot working it was time to draw up the schematic.  I first roughed it out on paper and then looked at what software to draw it up properly.  Normally I would use TinyCad as I had for my previous designs.  However I had in mind that I might want to have a professional pcb made up so I needed something with the functionality to generate the gerber files, drill plots, etc.

RS Components now have free schematic and pcb layout software package called DesignSpark.  Currently it runs only on Windows.  What is great about the software is the very extensive parts library and the option to link directly into RS Component's online store and search for parts, then download the schematic diagram and pcb layout information of that part.  Note that not all the components in RS components store are currently have this setup.  Free to use but you need to register to save your files.

Designspark comes with a nice tutorial which covers the process of schematic design, creating a pcb from that schematic and finally generating a BOM, gerber files, design reports, etc.  All in all very nice.  The best feature for me was the ease of generating a pcb and being able to generate a 3D view all in the one tool.

So final opinion?  I think I will keep trying out Designspark and use it for all my schematics going forward.  I'm sure the part library will only grow over time and the pcb layout functionality is very nice.

While originally keen to have a pcb made the cost has put me off.  The usual American offerings (expresspcb) are out due to postage costs.  There are local options (iTead for example) but for a one off board I'm still looking at the $80+ mark.  Point to point soldering here I come... once I work out the board layout.

Wednesday, July 31, 2013

Connecting the PNA4602 IR sensors to the PIC 16F628


As the PIC 16F628 has 5 interrupts (RB0/4-7) my design for the PNA4602 IR detectors is to have 5 detectors in total to detect the other sumo bot in the ring.  Two would be forward facing and one each for the left side/right side/rear.  The two forward detectors would operate in a crossed over (i.e. cross eyed) setup with the right detector looking left and the left detector looking right.  This would result in an overlap region at the front of pennybot.  Thus my detection regions are

forward left
directly forward (ie detected by both front sensors)
forward right
right side
rear
left side

I assigned the rear sensor to RB0 and the other four IR detectors to RB4-7.  I did this because I was toying with the idea of removing the rear IR sensor and instead using the RB0 interrupt pin for a front bump (ie micro switch) sensor.  It seemed a good way to separate between the two sets of interrupt pins.

To test each IR sensor the line was grounded as the PNA4602 goes low when a signal is detected.  This way the logic of what direction to turn depending on what sensor was activated could be easily tested.

On an aside two of the interrupt lines (RB6-7) are used for programming.  Since these two pins are normally at 5V (due to the PNA4602 output pin being high normally) this interfered with the in-circuit programming of the device.  After doing some web research the standard workaround for this was to put a resistor between the PicKit3 programmer and the rest of the circuit.   So going from the PNA4602 I have for both RB6 and RB7

PNA4602 -- 8.2K ohm resistor -- PIC16F628 RB6/7
    |
    -- PicKit3

Wednesday, February 27, 2013

PIC 16F628 and PNA4602 IR detectors

Each pin on the PIC 16F628 can only source 25mA.  To drive the IR leds I needed to use a transistor.  I selected a BC549 as it was listed as a signal transistor.  The voltage drop across each led was approx 1.2V so I should be able to drive 3 leds on a 5V line with a transistor.  Since I needed at least 5 IR leds (2 front, 1 left, 1 right, 1 back) I would need two transistors.  Next I had to calculate the minimum resistor value I could have that wouldn't result in more than 50mA being put through each led (the maximum an led could handle).  Initially I went with a very conservative resistor value of 1K. Doing number I found the minimum resistance as below:

2 IR leds

v/I = R
(5-(1.2*2)) / 50mA = R
52ohm = R


3 IR leds

v/I = R
(5-(1.2*3)) / 50mA = R
28ohm = R

For my initial tests I used just a single transistor with 3 IR leds connected.  Next was connecting up a single IR detector to the PIC.  I initially wanted to trial just one detector and a few IR leds in order to do range tests.  More on that later.

I used some PNA4602 detectors (the TSOP4038 seems more common now) which I had purchased from Solarbotics some time ago.  Yes, I was buying parts years before I got around to using them.  As widely recommended I put a 0.1uF capacitor across the power rail close to the detector.  The output of the detector went to pin RB4, one of the interrupt capable pins.  I setup in the ISR section that when the detector registered a hit, to turn left (thus changing one of the bicolor leds I've substituted for motors during testing).  Due to the blinking led loop I had in the main loop I could see when the detector (and thus ISR) was triggered.  Ie when I was in the ISR section the blinking led wouldn't be blinking.  Thus I had a double visual check that the detector was working as one of the dual colour leds I was using instead of motors would change color and in addition the blinking status led would stop blinking.  Now for range tests.

On my breadboard the IR leds and IR detector were approx a hand length apart and both pointing up at the ceiling.  Also I replaced the initial 1K resistor with my Variable resister box so I could adjust the power sent to the IR leds and thus the detector range.  So holding a ruler upright I slowly lowered my hand down the ruler.  I was looking for two things.  When the blinking led (from the main loop) stopped blinking, which would show the ISR had been entered.  The second was when the dual color led changed color from red to a solid green (not just a flickering green).  The results are below.

ResistanceDetectFull-Green
930ohm35cm18cm
530ohm43cm30cm
140ohm60cm+45cm

In the final circuit I plan to use a 1K variable resistor with the minimum safe resistor in series so I can tune on the fly.  The two front IR leds will be on one variable resistor, the left/right/rear IR leds will be on a second variable resistor.

Monday, January 21, 2013

SN754410 motor IC issues

By this stage I had a PWM signal and line detection working.  I decided it was time to integrate the two software components and the motor driver chip so I could observe the output of the logic decisions based on sensor inputs.  For the motor driver I used a SN754410 chip.  I had used this on a previous robot (squarebot) and I had a spare chip.  For testing instead of using motors I used dual colour leds to show the direction of the motors.  When the motor is going in one direction the led colour will be red, in the other direction the colour will be green.  I find the constant motor buzz gets distracting after awhile.  Also batteries die a lot faster.

I setup the logic so that when a line edge was detected the robot would turn away (ie right sensor detects a white line, turn left) or reverse if both line sensors were activated.  This wiring between the PIC and the SN754410 was quite simple with four outputs from the PIC going to the 4 H-bridge inputs on the SN754410.  The enable pins on the SN754410 I pulled high.  The motor power input came from the regulated 5V line.

In normal go forward mode this was fine.  However when the logic was to turn right all the leds went very dull.  Then I started seeing lock ups on the microcontroller.  Also the regulated 5V line would drop to under 3.5V when the motor chip was doing a "turn right".  I wasn't expecting the two motor leds to be drawing that much current so instead of the regulated 5V line I used an external battery pack for the SN754410 motor power input.  That stopped the led dimming.  However I knew that two leds with current limiting resistors shouldn't cause this.  

I then started to try and track down, was the issue related the the led/motor chip/microcontoller/something else.  Swapping parts showed that the leds were fine, thus it was when the PIC was saying turn right and the motor chip was doing so.  Swapping around the cabling from the PIC to the SN754410 show that the issue was with just one of the H-bridges on the SN754410.  So only when the H-bridge was having a certain output pin high did I see a high current draw.  The current draw went from 55mA up to 270mA when this was occurring.  Well past the limits of what a 9V battery can provide, hence the brownouts.  Taking the SN754410 from squarebot and swapping it in, no excessive current draw issue.  I had a dud SN754410 chip.  I binned that one and ordered 5 more from ebay that night.  Just love all these China/Hong Kong sellers with free shipping.

Now with my motor chip issues sorted it was time to move onto working with the IR part of the design.

Wednesday, December 12, 2012

PIC 16F628 PWM setup

As the primary detector sensors I wanted to use IR detectors as I had in previous robots.  Key to this is the generation of a 38khz square wave (50% duty cycle) which the IR detectors are tuned to.  In other robots I had used the circuit described in David Cook's Intermediate Robot Building book.  There are others based on 555 timer chips to.  However the pic16f628 has a PWM module and can output a PWM signal on one pin (RB3).  This meant one less extra IC chip and associated parts (resistors/capacitors).  However the setting up of the PWM was a little more esoteric.

I recommend reading the Microchip "PICmicro Mid-Range MCU Family Reference Manual".  The section on PWM makes the setup of PWM a lot clearer as there are some worked examples of the formulas used.  Without these I would have been pretty lost in time conversion hell.

Setting up PWM requires two main steps.  First is setting the frequency of the PWM.  The second is setting the duty cycle of the PWM.  Both the pic16f628 reference manual the the Mid-Range reference manual describe the formulas to do this.  Where things get interesting is that the PWM duty cycle is 10 bits and thus spread across two registers (CCPR1L and CCP1CON<5:4>).  Below is a worked example showing this.

First I set the PWM frequency to 38khz (ish).  For the TMR2 prescale I looked at the examples in the reference manual as a guide of what to set.  Like most of technology it's a case of seeing what someone else did and changing it to fit your specific case.  Via the equation with a 4mhz clock and a TMR2 prescale of 1

PWM period = (PR2 +1) * 4 * TOSC * TMR2 prescale
1/38kHz = (PR2 +1) * 4 * 1/4MHz * 1
26us = (PR2+1) * 4 * 0.25
26us = (PR2+1) * 1
25 = PR2

and the code with comments

; set pwm period
; 0x19 == 25 decimal.  So via equation
; 25+1 * 4 * 0.25 * 1 = 26
; 1/26 == 38khz ish
    banksel PR2
    movlw   0x19
    movwf   PR2

Then I set the duty cycle to 50%.  This means that the frequency will be twice that of the pwm.  Ie for each PWM period the duty cycle has to change twice (on, then off).  Thus the value to be put into the registers will be 0x34 (decimal 52 - 26*2).  This is split across the two registers.  The easiest way I found to do this was write out 0x34 as binary

0011 0100

Now this needs to be 10 bits, so the left most bits will be '00'

0000 1101 00

So CCPR1L will be '0000 1101' (0x0d) and CCP1CON<5:4> will be '00' (CCP1CON = 0x0c).  Code and comments below

; set pwm duty cycle to 50%
; so need duty cycle to be twice pwm period - ie 52 = 0x34
; since Tosc is in both pwm and duty cycle equation they cancel out
; remember split across bits 5/4 of ccp1con and ccpr1l
; ie 0000 1101 00
;  0x   0    d  0
    banksel CCP1CON
    movlw   0x0c
    movwf   CCP1CON
    movlw   0x0d
    movwf   CCPR1L  ; duty cycle 0x34 - ie 52 decimal
; set tmr2 prescaler 
    banksel T2CON
    movlw   0x00
    movwf   T2CON
; turn on timer 2
    bsf T2CON, TMR2ON

On the first attempt I got the duty cycle numbers wrong and saw no frequency output.  Stumped I ending up measuring the voltage on pin RB3.  It was 5V.  So the voltage was at VDD which is 5V which means I had a duty cycle of over 100%.  Reworking the numbers I spotted my error and fixed things up.  With a duty cycle of 50% the voltage was half VDD as expected.

On a side note I used a Casio FX-100d calculator to do the number crunching.  It's over 20 years old (I had it in high school) and is still running on the original battery.  Not sure what battery technology it has but I'm assuming it's an arc reactor subtype.

Tuesday, November 20, 2012

Pennybot line detection

The first piece of functionality I wanted to get working was the white line edge detection.  Previously I had used photoresistors and a LM393 comparator chip.  This time I wanted to try using LED Infra-red (IR) emitters and IR phototransitors detectors.  This was to reduce the impact of environmental light on the edge detection sensors.  Rather than a separate comparator chip I would use the comparator module in the pic16f628.  I had some nice 3mm LED IR emitter and 3mm phototransistor in a dual plastic housing that I had gotten from an old robot kit I had purchased purely for parts.  Not knowing the specs of either part I used a 1K resistor on the IR emitter.  For the phototransistor I wasn't sure the part was actually a phototransister.  As suggested in some example circuits I was using a 50K resistor in series.  There was very little response (ie voltage change) to changes in light level, less than 0.2 volts.  Trying a few different parts the result was the same.  Finally I guessed this was a IR only phototransistor.  Putting my finger to cover the IR LED and phototransistor (ie bouncing the IR led output back to the transistor) the transistor turned on - success!  The voltage range of the test point on the photo transistor from off to on was approx 4.8V (off) to 0.4V (on).  

Over on the microcontroller side of things I was using the comparator module as two common reference comparators (setting CM<2:0> = 011).  For the reference voltage I used a 10K pot to divide the 5V input and thus be able to tune the trigger point of the comparator.  I setup an ISR to trigger every time the comparator tripped.  The ISR incremented a counter and the main loop displayed this count in binary on 4 leds (the counter rolled over at 10).  Initially I was getting some twitchy responses with double counts, etc.  I added a 50ms delay in the ISR on the reading of the sensor and this was eliminated.  In addition to the counter being displayed I also toggled an led on port RA3 depending of the comparator output.  Code and comments below. 


    include "P16F628A.INC"        ;include the defaults for the chip
    list p=16f628a
    __config (_CP_OFF & _CPD_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF)

; ra0 / ra1 = inputs V-
; ra2 common V+
; ra3 output to led

; variables
    cblock 0x20
            OUTCOUNT ; interrupt code counter
            count ;used in delay routine
            count1 ;used in delay routine
            counta ;used in delay routine
            countb ;used in delay routine
    endc

    #define W_TEMP  0x70 ; common memory area across all banks
    #define STATUS_TEMP 0x71 ; temp vars for ISR

    org 0
    goto init   ; skip ISR code
;
; ISR code
;
    org 4
    movwf   W_TEMP        ; Save W & STATUS, etc
    swapf   STATUS, W
    bcf     STATUS, RP0
    movwf   STATUS_TEMP         ; end ISR save bits

    incf OUTCOUNT,1 ; COUNT +1, then check and reset count if needed
    movlw 0x0A ; put 10 in W
    subwf OUTCOUNT,0 ; subtract 10 from count to see if count > 10
    btfsc STATUS,0 ; check carry flag, skip if clear
    clrf OUTCOUNT ; reset count to 0

    call Delay50 ; wait 50ms for switch to get stable
    bcf STATUS,RP0 ; select bank 0
    btfsc CMCON,C2OUT ; if c2out is 1
    bsf PORTA,3 ; turn on ra3 led
    btfss CMCON,C2OUT ; if c2out is 0
    bcf PORTA,3 ; turn off ra3 led
    bcf PIR1, CMIF ; clear pending interrupts

    swapf   STATUS_TEMP, W   ; restore W & STATUS
    movwf   STATUS
    swapf   W_TEMP,F
    swapf   W_TEMP,W
    retfie                  ; end ISR end bits

init
    movlw 0x03 ; init comparator mode
    movwf CMCON ; CM<2:0> = 011
    bsf STATUS,RP0 ; select bank 1
    movlw 0x07 ; init data direction
    movwf TRISA ; ra2/0 as inputs, ra 4/3 as output
    movlw 0x00
    movwf TRISB ; all port b as output - for counter
    bcf STATUS,RP0 ; select bank 0
    movf CMCON,F ; read cmcon to end change condition wrt interrupt setup
    bcf PIR1, CMIF ; clear pending interrupts
    bsf STATUS, RP0 ; select bank 1
    bsf PIE1, CMIE ; enable comparator interrupts
    bcf STATUS,RP0 ; select bank 0 - determine initial state of comp output
    clrf PORTB ; clear portb
    btfsc CMCON,C2OUT ; if c2out is 1
    bsf PORTA,3 ; turn on ra3 led
    btfss CMCON,C2OUT ; if c2out is 0
    bcf PORTA,3 ; turn off ra3 led - finished initial state
    clrf OUTCOUNT ; init COUNT at 0
    bsf INTCON, PEIE ; enable peripheral interrupts
    bsf INTCON, GIE ; enable global interrupts 
main

    movf OUTCOUNT,0 ; COUNT to W
    movwf PORTB ; display count in hex on leds
    goto main

;Delay routines

Long_Delay
        movlw    d'50'        ;delay 5 seconds
        call    Delay100W
        return

Delay100W    movwf    count        ;delay W x 100mS
d2        call    Delay100    ;maximum delay 25.5 seconds
        decfsz    count    ,f
        goto    d2
        return

Delay255    movlw    0xff        ;delay 255 mS
        goto    d0
Delay100    movlw    d'100'        ;delay 100mS
        goto    d0
Delay50        movlw    d'50'        ;delay 50mS
        goto    d0
Delay20        movlw    d'20'        ;delay 20mS
        goto    d0
Delay10        movlw    d'10'        ;delay 10mS
        goto    d0
Delay1        movlw    d'1'        ;delay 1mS
        goto    d0
Delay5        movlw    0x05        ;delay 5.000 ms (4 MHz clock)
d0        movwf    count1
d1        movlw    0xC7
        movwf    counta
        movlw    0x01
        movwf    countb
Delay_0        decfsz    counta, f
        goto    $+2
        decfsz    countb, f
        goto    Delay_0

        decfsz    count1    ,f
        goto    d1
        return

;end of Delay routines

    end







Wednesday, November 14, 2012

Pennybot restart

Knowing as always time is short for robot building I wanted to break down the tasks to build pennybot into smaller achievable tasks that would take 1-2 weekends (I only get a few hours spare per weekend) to complete but would aid in the final design.  Putting the chassis aside for now as it was mainly complete I concentrated on the microcontroller.  I hadn't touched a microcontroller for 4 years so it was pretty much relearning from scratch.

The first thing to learn was MPLAB X.  I could have stuck with MPLAB 8 but it was time to move on.  I also had invested in a PicKit 3 as a serial port wasn't an option on any of the laptops I wanted to use for development.  I used a simple "blink the leds" assembly program as the trial experiment.  

I soldered up a little PicKit 3 breadboard header and cable, plugged everything in a hoped.  I fell down the usual holes along the way (power from board or from pickit for example) and got burnt by having to be strict on the formatting in the MPLAB editor.  Previously the text files could be pretty sloppy and still work with mpasm.  However the formatting rules made me do things the proper way, which saved me time when I came back after a week or so to review some code.  

I also jumped pic models to a pic16f628.  That's right, I upgraded to a ~10 year old pic.  One day I'll join the real world.  Not having to have an external timing crystal (and getting two pins back) and the comparator module onboard were a big plus.  Also it was a very simple cutover from the pic16f84.  Finally I could buy (and did) 5 pic16f628 chips for $10 off ebay.  This means I have enough for this project and a few others so any investment in time in learning to program this model would pay off.  This did mean that C was pretty much out of the picture.  However I liked learning how to do things in assembly.  I enjoy having that real low level knowledge of what is going on even if the setup on some features (eg pwm) can get a bit messy.

I started development on a Windows 7 desktop.  After awhile I moved onto a linux laptop.  The only issue I had was the include statement.  In Linux (which is case sensitive) the include file is in capitals.  Everything else was fine.  So with MPLABX and the PicKit 3 sorted out it was time to do some real programs.