1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

PWM controlls, best chip for several at once? AVR or PIC

Discussion in 'Microcontrollers' started by Triode, May 3, 2009.

  1. Leftyretro

    Leftyretro New Member

    Joined:
    Mar 11, 2007
    Messages:
    1,420
    Likes:
    13
    Location:
    Hercules, California
    While it is a form of PWM, Nigel's point is valid. Most micro's hardware PWM modules aren't designed well for emulating the decoded PPM signal that a standard servo is designed to accept. If the PWM hardware is set up for a 20 millsec period (frame refresh rate) then the 0% (1msec) to 100% (2 msec) servo travel represents a duty cycle range of only 5% to 10% of the total duty cycle range. This doesn't allow very good resolution as the full duty cycle resolution has to be able to cover 0-20mec. So in a 10 bit duty cycle PWM module only around 50 'counts' will be avalible for the actual servo travel and that's not very good resolution, effectivly only about a 6 bit resolution, OK for some applications, but a servo is capable of better.

    That make sense or have I got it all wrong?

    Lefty
     
    Last edited: May 5, 2009
  2. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    Yes, I would say your comment on resolution being poor in the example you gave is correct.
     
  3. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,203
    Likes:
    640
    Location:
    Derbyshire, UK
    Considering you were talking about something completely different to what this thread is about, it's pretty obvious it's your mistake! :D
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area

    That’s true Nigel, but as off topic as this discussion/argument may be, I'm still getting some good information from it. So much more interesting than forums where when the discussion breaks down the subject turns to who’s mother is more promiscuous, and who is a homosexual.
     
  6. nickelflippr

    nickelflippr Member

    Joined:
    Oct 20, 2006
    Messages:
    891
    Likes:
    18
    Location:
    Oregon, USA
    Getting back to the original question of 3 inputs and 3 output PWM's, a PIC 18fxx31 series chip would give you 3 to 4 channels of 14 bit PWM. This is assuming that the three inputs would in fact be three different channels on a single RX PPM stream.

    On a Vex transmitter/receiver the synch pulse was around 8ms (low), the start pulse about .5ms(high) and the variable servo pulse was about 0.65-1.45ms(low).
     
  7. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,203
    Likes:
    640
    Location:
    Derbyshire, UK
    Again, this is nothing to do with the original question? - who cares about the carrier transmisisons, the only outputs he has access to are the servo outputs from the receiver, which are a single 1-2mS pulse repeated every 20mS.

    But actually going back to the original question, he only requires two PWM outputs, as he is only feeding two motors. If he cares to check my PWM tutorial it uses a 16F876 to feed hardware PWM speed control, plus two switching lines per motor, to control two DC motors - designed for a normal little robot.
     
  8. nickelflippr

    nickelflippr Member

    Joined:
    Oct 20, 2006
    Messages:
    891
    Likes:
    18
    Location:
    Oregon, USA
    Well my mistake for jumping in late on topic, I should know better:(. I see now the OP's parameters are constantly changing. Anyway, the Vex transmitter/receiver combo is in fact the raw transmitter signal and needs to be decoded. An option that seems to have been discarded.

    Here's what the post was based on, didn't realize those were already decoded inputs.
     
  9. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    I didnt realize vex worked that way, so that would explain some of the confusion. Anyway, I'll be using traxxas and futaba, so I dont think it will come up. For what I can tell vex is no better but costs a lot more because it says its for robots.

    Nigel, thanks, I'll go through your tutorial on this.
     
  10. nickelflippr

    nickelflippr Member

    Joined:
    Oct 20, 2006
    Messages:
    891
    Likes:
    18
    Location:
    Oregon, USA
    Yea the little phone connector goes to the Vex controller box for processing. I think you are on the right track. Retail on the Vex transmitter is high.

    A year ago or so it seemed the surplus channels and ebay were flooded with the Vex transmitters, got mine for $20usd. The supply seems to be drying up, still there was one on ebay for under $30. Have to decode the raw stream though.
     
  11. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,203
    Likes:
    640
    Location:
    Derbyshire, UK
    I don't know if this will help or not?, the following code was written as an example of doing what you want back in 2002, reading two lots of servo pulses from an R/C receiver, and controlling two DC motors in a skid steering configuration. Joystick forwards and backwards gives speed forwards and backwards, left to right gives steering, just like driving a model car.

    It will at least give you some idea of how to do it, but the code was written using my own BASIC compiler that I was writing back then, so won't compile under anything else, but it should give you an idea of how it can be done.

    If you're interested in playing with the assembler code it generates, I can send you that - my compiler produces easy to read sensible code, with the original BASIC source nicely inserted as comments.

    Code (text):
    Device 16F876
    Dim Speed, Steer, C, Dead, Left, Right, Error
    Freq=20
    Define PortC=%00000000
    Define PortB=%11111111
    Define PortA=%11111111
    Dead=30 'set dead band value
    Set(CCP1=PWM)  
    Set(CCP2=PWM)
    PERIOD_REG=249
    Set(TIMER2_PRESCALER=1)
    Set(TIMER2_POSTSCALER=1)
    START(TIMER2)
    OUTC(0)
    OUTB(0)
    Error=0
    ReStart:
    Left=0
    Right=0
    Loop:
        PWM_Duty1L=Left
        PWM_Duty2L=Right
        Speed=Pulsein(portB, 7, 1)
        If Speed=0 Then Goto NoPulse
        If Speed>750 Then Speed=750
        If Speed<250 Then Speed=250
        Steer=Pulsein(portB, 6, 1)
        If Steer=0 Then Goto NoPulse
        Error=0             'both pulses OK
        If Steer>750 Then Steer=750
        If Steer<250 Then Steer=250
        Steer=Steer-250
        If Steer<250 Then Gosub TurnLeft
        If Steer>249 Then Gosub TurnRight
    Goto Loop

    NoPulse:
        Error=Error+1
        If Error > 5 Then Goto ReStart
        Goto Loop

    TurnLeft:
        C=250-Steer
        Right=Speed+C
        Left=Speed-C
        Gosub Scale
    Return

    TurnRight:
        C=Steer-250
        Left=Speed+C
        Right=Speed-C
        Gosub Scale
    Return

    Scale:
        Right=Right-250
        Left=Left-250
        If Left>10000 Then Left=0   'correct for negative number
        If Right>10000 Then Right=0 'correct for negative number
        If Right>500 Then Right=500
        If Left>500 Then Left=500
        If Right<250 Then Goto ReverseA
        Goto ForwardA
    Do_Left:
        If Left<250 Then Goto ReverseB
        Goto ForwardB
    Done_Left:
    Return

    ReverseA:
        Right=250-Right
        Gosub Check_Dead
        High PortC, 3
    Goto Do_Left

    ForwardA:
        Right=Right-250
        Gosub Check_Dead
        Low PortC, 3
    Goto Do_Left

    ReverseB:
        Left=250-Left
        Gosub Check_Dead
        High PortC, 4
    Goto Done_Left

    ForwardB:
        Left=Left-250
        Gosub Check_Dead
        Low PortC, 4
    Goto Done_Left

    Check_Dead:
        If Right<Dead Then Right=0
        If Left<Dead Then Left=0
    Return

    end

     
     
  12. jeremygaughan

    jeremygaughan New Member

    Joined:
    Sep 26, 2007
    Messages:
    129
    Likes:
    1
    Location:
    Hot Springs, AR
    I'd like to see that in assembler if possible.
     
  13. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,203
    Likes:
    640
    Location:
    Derbyshire, UK
    OK, here's the assembler it produces, notice it uses two include files as well, one provides all the maths functions, the other is dynamically created for the rest the program might need.

    Code (text):
    ; WinPicProg BASIC Compiler Version1.9
    ;
    ; Device 16F876
        LIST P=16F876, W=2, X=ON, R=DEC
        #INCLUDE P16F876.INC
        __CONFIG    0x393A
    ;Flags register bit definitions
    LEADZ         EQU   0x00   ;set to show leading zeros
    Lo            EQU   0x05   ;set for I2C normal addressing
    Hi            EQU   0x06   ;set for I2C extended addressing
    Err           EQU   0x07   ;set for I2C error
    ;Pre-defined variables
    TEMP1         EQU   32
    TEMP2         EQU   33
    RESTORE       EQU   34
    TEMP1_DU      EQU   35
    TEMP2_DU      EQU   36
    RESTORE_DU    EQU   37
    W_DU          EQU   38
    STATUS_DU     EQU   39
    Bit_Cntr      EQU   40
    Xmit_Byte     EQU   41
    Rcv_Byte      EQU   42
    LCD_DAT1      EQU   43
    Delay_Count   EQU   44
    _N            EQU   44
    LCD_DAT2      EQU   45
    LCD_DAT3      EQU   46
    TEMP_LCD      EQU   47
    TEMP_LCD2     EQU   48
    DELAY1        EQU   49
    state         EQU   50
    pin           EQU   51
    hiRnd         EQU   52
    lowRnd        EQU   53
    Acc1L         EQU   54
    Acc1H         EQU   55
    Acc2L         EQU   56
    Acc2H         EQU   57
    Acc3L         EQU   58
    Acc3H         EQU   59
    Flags         EQU   60
    TenK          EQU   61
    Thou          EQU   62
    Hund          EQU   63
    Tens          EQU   64
    Ones          EQU   65
    Adr_Lo        EQU   66
    Adr_Hi        EQU   67
    Chip_Adr      EQU   68
    Data_Page     EQU   69
        ORG      0x00
        GOTO     _START1
        ORG      0x010
        #INCLUDE HANDLERS.INC
        #INCLUDE MATHS.INC
    _START1
        CLRF     RESTORE
        CLRF     Flags
        BCF      Flags, LEADZ
        BANKSEL  ADCON1
        MOVLW    0x06
        MOVWF    ADCON1
        BANKSEL  PORTA
    ; Dim Speed, Steer, C, Dead, Left, Right, Error
    VAR2    EQU      70;Speed
    VAR4    EQU      72;Steer
    VAR6    EQU      74;C
    VAR8    EQU      76;Dead
    VAR10    EQU      78;Left
    VAR12    EQU      80;Right
    VAR14    EQU      82;Error
    ; Freq=20
    ; Oscillator frequency set to 20MHz
    ; Define PortC=%00000000
        BANKSEL  TRISC
        MOVLW    0
        MOVWF    TRISC
        BANKSEL  PORTC
    ; Define PortB=%11111111
        BANKSEL  TRISB
        MOVLW    255
        MOVWF    TRISB
        BANKSEL  PORTB
    ; Define PortA=%11111111
        BANKSEL  TRISA
        MOVLW    255
        MOVWF    TRISA
        BANKSEL  PORTA
    ; Dead=30
        MOVLW    0
        MOVWF    VAR8+1
        MOVLW    30
        MOVWF    VAR8
    ; Set(CCP1=PWM)
        MOVF     CCP1CON,W
        ANDLW    0xF0
        IORLW    0x0C
        MOVWF    CCP1CON
    ; Set(CCP2=PWM)
        MOVF     CCP2CON,W
        ANDLW    0xF0
        IORLW    0x0C
        MOVWF    CCP2CON
    ; PERIOD_REG=249
        MOVLW    249
        BANKSEL  PR2
        MOVWF    PR2
        BANKSEL  TMR2
    ; Set(TIMER2_PRESCALER=1)
        MOVF     T2CON,W
        ANDLW    0xF8
        IORLW    0x00
        MOVWF    T2CON
    ; Set(TIMER2_POSTSCALER=1)
        MOVF     T2CON,W
        ANDLW    0x07
        IORLW    0x00
        MOVWF    T2CON
    ; START(TIMER2)
        BSF      T2CON, TMR2ON
    ; OUTC(0)
        MOVLW    0
        MOVWF    PORTC
    ; OUTB(0)
        MOVLW    0
        MOVWF    PORTB
    ; Error=0
        MOVLW    0
        MOVWF    VAR14+1
        MOVLW    0
        MOVWF    VAR14
    ; ReStart:
    LAB1:
    ; Left=0
        MOVLW    0
        MOVWF    VAR10+1
        MOVLW    0
        MOVWF    VAR10
    ; Right=0
        MOVLW    0
        MOVWF    VAR12+1
        MOVLW    0
        MOVWF    VAR12
    ; Loop:
    LAB2:
    ; PWM_Duty1L=Left
        MOVF     VAR10,W
        MOVWF    CCPR1L
    ; PWM_Duty2L=Right
        MOVF     VAR12,W
        MOVWF    CCPR2L
    ; Speed=Pulsein(portB, 7, 1)
        MOVLW    7
        MOVWF    pin
        MOVLW    0xFF
        MOVWF    state
        MOVLW    1
        CALL     _PULSEIN
        MOVF     Acc1L, w
        MOVWF    VAR2
        MOVF     Acc1H, W
        MOVWF    VAR2+1
    ; If Speed=0 Then Goto NoPulse
        MOVF     VAR2+1 ,W
        MOVWF    Acc1H
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    0
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSS    STATUS, Z
        GOTO     IFLAB1
    ; Goto NoPulse
        GOTO LAB3
    IFLAB1:
    ; If Speed>750 Then Speed=750
        MOVF     VAR2+1 ,W
        MOVWF    Acc1H
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVLW    2
        MOVWF    Acc2H
        MOVLW    238
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB2
    ; Speed=750
        MOVLW    2
        MOVWF    VAR2+1
        MOVLW    238
        MOVWF    VAR2
    IFLAB2:
    ; If Speed<250 Then Speed=250
        MOVF     VAR2+1 ,W
        MOVWF    Acc1H
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    250
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB3
    ; Speed=250
        MOVLW    0
        MOVWF    VAR2+1
        MOVLW    250
        MOVWF    VAR2
    IFLAB3:
    ; Steer=Pulsein(portB, 6, 1)
        MOVLW    6
        MOVWF    pin
        MOVLW    0xFF
        MOVWF    state
        MOVLW    1
        CALL     _PULSEIN
        MOVF     Acc1L, w
        MOVWF    VAR4
        MOVF     Acc1H, W
        MOVWF    VAR4+1
    ; If Steer=0 Then Goto NoPulse
        MOVF     VAR4+1 ,W
        MOVWF    Acc1H
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    0
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSS    STATUS, Z
        GOTO     IFLAB4
    ; Goto NoPulse
        GOTO LAB3
    IFLAB4:
    ; Error=0
        MOVLW    0
        MOVWF    VAR14+1
        MOVLW    0
        MOVWF    VAR14
    ; If Steer>750 Then Steer=750
        MOVF     VAR4+1 ,W
        MOVWF    Acc1H
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVLW    2
        MOVWF    Acc2H
        MOVLW    238
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB5
    ; Steer=750
        MOVLW    2
        MOVWF    VAR4+1
        MOVLW    238
        MOVWF    VAR4
    IFLAB5:
    ; If Steer<250 Then Steer=250
        MOVF     VAR4+1 ,W
        MOVWF    Acc1H
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    250
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB6
    ; Steer=250
        MOVLW    0
        MOVWF    VAR4+1
        MOVLW    250
        MOVWF    VAR4
    IFLAB6:
    ; Steer=Steer-250
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVF     VAR4+1,W
        MOVWF    Acc1H
        MOVLW    250
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR4
        MOVF     Acc1H, W
        MOVWF    VAR4+1
    ; If Steer<250 Then Gosub TurnLeft
        MOVF     VAR4+1 ,W
        MOVWF    Acc1H
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    250
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB7
    ; Gosub TurnLeft
        CALL     LAB4
    IFLAB7:
    ; If Steer>249 Then Gosub TurnRight
        MOVF     VAR4+1 ,W
        MOVWF    Acc1H
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    249
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB8
    ; Gosub TurnRight
        CALL     LAB5
    IFLAB8:
    ; Goto Loop
        GOTO LAB2
    ; NoPulse:
    LAB3:
    ; Error=Error+1
        MOVF     VAR14,W
        MOVWF    Acc1L
        MOVF     VAR14+1,W
        MOVWF    Acc1H
        MOVLW    1
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Add16
        MOVF     Acc1L, W
        MOVWF    VAR14
        MOVF     Acc1H, W
        MOVWF    VAR14+1
    ; If Error > 5 Then Goto ReStart
        MOVF     VAR14+1 ,W
        MOVWF    Acc1H
        MOVF     VAR14,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    5
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB9
    ; Goto ReStart
        GOTO LAB1
    IFLAB9:
    ; Goto Loop
        GOTO LAB2
    ; TurnLeft:
    LAB4:
    ; C=250-Steer
        MOVLW    250
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc1H
        MOVF     VAR4,W
        MOVWF    Acc2L
        MOVF     VAR4+1,W
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR6
        MOVF     Acc1H, W
        MOVWF    VAR6+1
    ; Right=Speed+C
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVF     VAR2+1,W
        MOVWF    Acc1H
        MOVF     VAR6,W
        MOVWF    Acc2L
        MOVF     VAR6+1,W
        MOVWF    Acc2H
        CALL     _Add16
        MOVF     Acc1L, W
        MOVWF    VAR12
        MOVF     Acc1H, W
        MOVWF    VAR12+1
    ; Left=Speed-C
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVF     VAR2+1,W
        MOVWF    Acc1H
        MOVF     VAR6,W
        MOVWF    Acc2L
        MOVF     VAR6+1,W
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR10
        MOVF     Acc1H, W
        MOVWF    VAR10+1
    ; Gosub Scale
        CALL     LAB6
    ; Return
        RETURN
    ; TurnRight:
    LAB5:
    ; C=Steer-250
        MOVF     VAR4,W
        MOVWF    Acc1L
        MOVF     VAR4+1,W
        MOVWF    Acc1H
        MOVLW    250
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR6
        MOVF     Acc1H, W
        MOVWF    VAR6+1
    ; Left=Speed+C
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVF     VAR2+1,W
        MOVWF    Acc1H
        MOVF     VAR6,W
        MOVWF    Acc2L
        MOVF     VAR6+1,W
        MOVWF    Acc2H
        CALL     _Add16
        MOVF     Acc1L, W
        MOVWF    VAR10
        MOVF     Acc1H, W
        MOVWF    VAR10+1
    ; Right=Speed-C
        MOVF     VAR2,W
        MOVWF    Acc1L
        MOVF     VAR2+1,W
        MOVWF    Acc1H
        MOVF     VAR6,W
        MOVWF    Acc2L
        MOVF     VAR6+1,W
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR12
        MOVF     Acc1H, W
        MOVWF    VAR12+1
    ; Gosub Scale
        CALL     LAB6
    ; Return
        RETURN
    ; Scale:
    LAB6:
    ; Right=Right-250
        MOVF     VAR12,W
        MOVWF    Acc1L
        MOVF     VAR12+1,W
        MOVWF    Acc1H
        MOVLW    250
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR12
        MOVF     Acc1H, W
        MOVWF    VAR12+1
    ; Left=Left-250
        MOVF     VAR10,W
        MOVWF    Acc1L
        MOVF     VAR10+1,W
        MOVWF    Acc1H
        MOVLW    250
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR10
        MOVF     Acc1H, W
        MOVWF    VAR10+1
    ; If Left>10000 Then Left=0
        MOVF     VAR10+1 ,W
        MOVWF    Acc1H
        MOVF     VAR10,W
        MOVWF    Acc1L
        MOVLW    39
        MOVWF    Acc2H
        MOVLW    16
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB10
    ; Left=0
        MOVLW    0
        MOVWF    VAR10+1
        MOVLW    0
        MOVWF    VAR10
    IFLAB10:
    ; If Right>10000 Then Right=0
        MOVF     VAR12+1 ,W
        MOVWF    Acc1H
        MOVF     VAR12,W
        MOVWF    Acc1L
        MOVLW    39
        MOVWF    Acc2H
        MOVLW    16
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB11
    ; Right=0
        MOVLW    0
        MOVWF    VAR12+1
        MOVLW    0
        MOVWF    VAR12
    IFLAB11:
    ; If Right>500 Then Right=500
        MOVF     VAR12+1 ,W
        MOVWF    Acc1H
        MOVF     VAR12,W
        MOVWF    Acc1L
        MOVLW    1
        MOVWF    Acc2H
        MOVLW    244
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB12
    ; Right=500
        MOVLW    1
        MOVWF    VAR12+1
        MOVLW    244
        MOVWF    VAR12
    IFLAB12:
    ; If Left>500 Then Left=500
        MOVF     VAR10+1 ,W
        MOVWF    Acc1H
        MOVF     VAR10,W
        MOVWF    Acc1L
        MOVLW    1
        MOVWF    Acc2H
        MOVLW    244
        MOVWF    Acc2L
        CALL     _COMP16
        BTFSC    STATUS, C
        GOTO     IFLAB13
    ; Left=500
        MOVLW    1
        MOVWF    VAR10+1
        MOVLW    244
        MOVWF    VAR10
    IFLAB13:
    ; If Right<250 Then Goto ReverseA
        MOVF     VAR12+1 ,W
        MOVWF    Acc1H
        MOVF     VAR12,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    250
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB14
    ; Goto ReverseA
        GOTO LAB7
    IFLAB14:
    ; Goto ForwardA
        GOTO LAB8
    ; Do_Left:
    LAB9:
    ; If Left<250 Then Goto ReverseB
        MOVF     VAR10+1 ,W
        MOVWF    Acc1H
        MOVF     VAR10,W
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc2H
        MOVLW    250
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB15
    ; Goto ReverseB
        GOTO LAB10
    IFLAB15:
    ; Goto ForwardB
        GOTO LAB11
    ; Done_Left:
    LAB12:
    ; Return
        RETURN
    ; ReverseA:
    LAB7:
    ; Right=250-Right
        MOVLW    250
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc1H
        MOVF     VAR12,W
        MOVWF    Acc2L
        MOVF     VAR12+1,W
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR12
        MOVF     Acc1H, W
        MOVWF    VAR12+1
    ; Gosub Check_Dead
        CALL     LAB13
    ; High PortC, 3
        BSF    PORTC, 3
    ; Goto Do_Left
        GOTO LAB9
    ; ForwardA:
    LAB8:
    ; Right=Right-250
        MOVF     VAR12,W
        MOVWF    Acc1L
        MOVF     VAR12+1,W
        MOVWF    Acc1H
        MOVLW    250
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR12
        MOVF     Acc1H, W
        MOVWF    VAR12+1
    ; Gosub Check_Dead
        CALL     LAB13
    ; Low PortC, 3
        BCF    PORTC, 3
    ; Goto Do_Left
        GOTO LAB9
    ; ReverseB:
    LAB10:
    ; Left=250-Left
        MOVLW    250
        MOVWF    Acc1L
        MOVLW    0
        MOVWF    Acc1H
        MOVF     VAR10,W
        MOVWF    Acc2L
        MOVF     VAR10+1,W
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR10
        MOVF     Acc1H, W
        MOVWF    VAR10+1
    ; Gosub Check_Dead
        CALL     LAB13
    ; High PortC, 4
        BSF    PORTC, 4
    ; Goto Done_Left
        GOTO LAB12
    ; ForwardB:
    LAB11:
    ; Left=Left-250
        MOVF     VAR10,W
        MOVWF    Acc1L
        MOVF     VAR10+1,W
        MOVWF    Acc1H
        MOVLW    250
        MOVWF    Acc2L
        MOVLW    0
        MOVWF    Acc2H
        CALL     _Sub16
        MOVF     Acc1L, W
        MOVWF    VAR10
        MOVF     Acc1H, W
        MOVWF    VAR10+1
    ; Gosub Check_Dead
        CALL     LAB13
    ; Low PortC, 4
        BCF    PORTC, 4
    ; Goto Done_Left
        GOTO LAB12
    ; Check_Dead:
    LAB13:
    ; If Right<Dead Then Right=0
        MOVF     VAR12+1 ,W
        MOVWF    Acc1H
        MOVF     VAR12,W
        MOVWF    Acc1L
        MOVF     VAR8+1 ,W
        MOVWF    Acc2H
        MOVF     VAR8,W
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB16
    ; Right=0
        MOVLW    0
        MOVWF    VAR12+1
        MOVLW    0
        MOVWF    VAR12
    IFLAB16:
    ; If Left<Dead Then Left=0
        MOVF     VAR10+1 ,W
        MOVWF    Acc1H
        MOVF     VAR10,W
        MOVWF    Acc1L
        MOVF     VAR8+1 ,W
        MOVWF    Acc2H
        MOVF     VAR8,W
        MOVWF    Acc2L
        CALL     _COMP16I
        BTFSC    STATUS, C
        GOTO     IFLAB17
    ; Left=0
        MOVLW    0
        MOVWF    VAR10+1
        MOVLW    0
        MOVWF    VAR10
    IFLAB17:
    ; Return
        RETURN
    ; end
        CLRWDT
        SLEEP
        END
    ;
    ;Number of variables used:82 out of 127
     
     
  14. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,203
    Likes:
    640
    Location:
    Derbyshire, UK
    And here are the two include files:

    Code (text):
        NOLIST
    _PULSEIN     CLRF     Acc1L
        CLRF     Acc1H
        MOVWF    FSR
        MOVLW    0x05
        ADDWF    FSR
        MOVF     pin, w
        CALL     _PINZ
        MOVWF    pin
        ANDWF    state
    Pulsin_Hold  MOVF     INDF, w
        ANDWF    pin, w
        XORWF    state, w
        BTFSS    STATUS, Z
        GOTO     Pulsin_doneH
        INCF     Acc1L
        BTFSC    STATUS, Z
        INCFSZ   Acc1H
        GOTO     Pulsin_Hold
        GOTO     Pulsin_Error
    Pulsin_doneH CLRF     Acc1L
        CLRF     Acc1H
    Pulsin_Edge1 MOVF     INDF, w
        ANDWF    pin, w
        XORWF    state, w
        BTFSC    STATUS, Z
        GOTO     Pulsin_doneE
        INCF     Acc1L
        BTFSC    STATUS, Z
        INCFSZ   Acc1H
        GOTO     Pulsin_Edge1
        GOTO     Pulsin_Error
    Pulsin_doneE CLRF     Acc1L
        CLRF     Acc1H
    Pulsin_Edge2 MOVF     INDF, w
        ANDWF    pin, w
        XORWF    state, w
        BTFSS    STATUS, Z
        RETURN
        INCF     Acc1L
        BTFSC    STATUS, Z
        INCFSZ   Acc1H
        GOTO     Pulsin_Edge2
    Pulsin_Error CLRF     Acc1L
        CLRF     Acc1H
        RETURN
        LIST
     

    Code (text):
        NOLIST
    _PINZ        ADDWF PCL
        RETLW d'1'
        RETLW d'2'
        RETLW d'4'
        RETLW d'8'
        RETLW d'16'
        RETLW d'32'
        RETLW d'64'
        RETLW d'128'
    _Sub16       COMF   Acc2H       ; Take two's complement
        COMF   Acc2L       ; of Acc2. If zero, Acc2L
        INCF   Acc2L
        BTFSC  STATUS, Z   ; overflowed, so carry
        INCF   Acc2H       ; into Acc2H.
    _Add16       BCF    Flags, OverFlow ; clear overflow flag
        MOVF   Acc2L, w    ; Add the LSBs. If carry,
        ADDWF  Acc1L
        BTFSC  STATUS, C   ; increment MSB of sum.
        INCF   Acc1H
        MOVF   Acc2H, w    ; Add the MSBs
        ADDWF  Acc1H
        BTFSC  STATUS, C   ; check for sum overflow
        BSF    Flags, OverFlow ; set overflow flag
        MOVF   Acc1L, w    ; return lobyte in W
        RETURN
    _Mult16
        CLRF   Acc3H          ; Clear product to make
        CLRF   Acc3L         ; way for new calculation.
        MOVLW  d'16'        ; Number of bits to calc.
        MOVWF  TEMP1
    Multiply_loop
        BCF    STATUS, C
        RLF    Acc3L         ; Shift product left.
        RLF    Acc3H
        BCF    STATUS, C
        RLF    Acc1L        ; Shift multiplicand left.
        RLF    Acc1H
        BTFSS  STATUS, C    ; If carry, add multiplier
        GOTO   Multiply_skip
        MOVF   Acc2L,w      ; to the product. Else skip.
        ADDWF  Acc3L
        BTFSC  STATUS, C    ; 16-bit addition: prod+mulp
        INCF   Acc3H
        MOVF   Acc2H, w
        ADDWF  Acc3H
    Multiply_skip
        DECFSZ TEMP1
        GOTO   Multiply_loop
        MOVF   Acc3H, w
        MOVWF  Acc1H        ; return answer in Acc1
        MOVF   Acc3L, w
        MOVWF  Acc1L        ; with lobyte in W
        RETURN
    _DIV16          MOVF    Acc2H, w                ; Check for division by 0.
        IORWF   Acc2L, w
        BTFSC   STATUS, Z
        RETLW   d'255'        ; Error code= 255: return.
        MOVLW   d'1'          ; Otherwise, initialize variables
        MOVWF   TEMP1
        CLRF    TEMP2         ; index for the division.
        CLRF    Acc3H
        CLRF    Acc3L
    Divide_sh_loop  BTFSC   Acc2H, d'7'   ; Shift divisor left
        GOTO    Divide_d1
        BCF     STATUS, C     ; until msb is in
        RLF     Acc2L         ; Acc2H.7.
        RLF     Acc2H         ; TEMP1 = no. of shifts+1.
        INCF    TEMP1
        GOTO    Divide_sh_loop
    Divide_d1       BCF     STATUS, C
        RLF     Acc3L          ; Shift quotient left.
        RLF     Acc3H
        MOVF    Acc2L,w       ; top = top - btm.
        SUBWF   Acc1L
        BTFSC   STATUS, C     ; If top - btm < 0 then
        GOTO    Divide_d2
        MOVLW   d'1'          ; top = top + btm
        SUBWF   Acc1H
        BTFSC   STATUS, C     ; The idea is to do the
        GOTO    Divide_d2
        INCF    Acc1H         ; the subtraction and comparison
        MOVF    Acc2L, w      ; (top > btm?) in one step.
        ADDWF   Acc1L
        goto    Divide_reentr ; Then, if btm > top, undo <Microchip instruction>
    Divide_d2       MOVF    Acc2H, w      ; the subtraction by adding
        SUBWF   Acc1H
        BTFSS   STATUS, C     ; top and btm back together
        goto    Divide_less   ; <Microchip instruction>
        BSF     Acc3L,  d'0'
    Divide_reentr
        BCF     STATUS, C
        RRF     Acc2H
        RRF     Acc2L
        DECFSZ  TEMP1
        GOTO    Divide_d1
        MOVF    Acc3H, w
        MOVWF   Acc1H         ; return answer in Acc1
        MOVF    Acc3L, w
        MOVWF   Acc1L         ; with lobyte in W
        RETURN
    Divide_less     MOVF    Acc2L, w      ; btm > top, so
        ADDWF   Acc1L
        BTFSC   STATUS, C     ; undo the subtraction by
        INCF    Acc1H         ; adding them back together.
        MOVF    Acc2H, w
        ADDWF   Acc1H
        goto    Divide_reentr ; <Microchip instruction>
    _SHIFTR         MOVWF    Acc2L
    _LoopR          BCF      STATUS, C
        RRF      Acc1H, F
        RRF      Acc1L, F
        DECFSZ   Acc2L
        GOTO     _LoopR
        MOVF     Acc1L, W
        RETURN
    _SHIFTL         MOVWF    Acc2L
    _LoopL          BCF      STATUS, C
        RLF      Acc1L, F
        RLF      Acc1H, F
        DECFSZ   Acc2L
        GOTO     _LoopL
        MOVF     Acc1L, W
        RETURN
    _CONVERT:                       ; Takes number in Acc1H:Acc1L
        ; Returns decimal in
        ; TenK:Thou:Hund:Tens:Ones
        swapf   Acc1H, w
        iorlw   B'11110000'
        movwf   Thou
        addwf   Thou,f
        addlw   0XE2
        movwf   Hund
        addlw   0X32
        movwf   Ones
        movf    Acc1H,w
        andlw   0X0F
        addwf   Hund,f
        addwf   Hund,f
        addwf   Ones,f
        addlw   0XE9
        movwf   Tens
        addwf   Tens,f
        addwf   Tens,f
        swapf   Acc1L,w
        andlw   0X0F
        addwf   Tens,f
        addwf   Ones,f
        rlf     Tens,f
        rlf     Ones,f
        comf    Ones,f
        rlf     Ones,f
        movf    Acc1L,w
        andlw   0X0F
        addwf   Ones,f
        rlf     Thou,f
        movlw   0X07
        movwf   TenK
        movlw   0X0A
    Lb1:
        addwf   Ones,f
        decf    Tens,f
        btfss   3,0
        goto   Lb1
    Lb2:
        addwf   Tens,f
        decf    Hund,f
        btfss   3,0
        goto   Lb2
    Lb3:
        addwf   Hund,f
        decf    Thou,f
        btfss   3,0
        goto   Lb3
    Lb4:
        addwf   Thou,f
        decf    TenK,f
        btfss   3,0
        goto   Lb4
        return
    _COMP16:
        movf    Acc1H, w
        subwf   Acc2H, w
        btfss   STATUS, Z
        goto    $+3
        movf    Acc1L, w
        subwf   Acc2L,
        return
    _COMP16I:
        movf    Acc2H, w
        subwf   Acc1H, w
        btfss   STATUS, Z
        goto    $+3
        movf    Acc2L, w
        subwf   Acc1L, w
        return
        LIST
     
     
  15. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    I'm going to see if I can get an LCD working so I can get a readout for debugging before I work on the other aspects of this. I don't have one of those character LCD modules but I have an 4 character 7 segment LCD and a 16F916 which is supposed to be made for driving those so I should be able to do it. I'm not really sure how you hook these up but I'm sure I can work it out over time. Does it have one pin that you ground then charge the others to darken the segments? Or is it the other way around? or perhapse a different arrangement all together? Thats what I'm working on at the moment.

    [​IMG]
    it says "PLANAR SYSTEMS, INC. 0103-3906-365-483-01" and so far I haven't been able to find anything with that, but im hoping that they are similar enough and this is simple enough that I can get it without a manual.

    I have gotten it plugged into my breadboard with some effort. I've connected 9 volts to it and i can make the cells darken individually by touching the pins, but so far I haven't figured out how to clear them. It doesnt seem to matter which pin i connect the other lead to or which lead I use to touch different pins and which one I leave connected. when I light it all up its one of these "8.8:8.8"
     
  16. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    The small bias voltage a multimeter puts out in diode test mode is perfect for testing these kinds of displays, I'm guessing there's going to be a few different grounds, maybe one for each character, but I'm just guessing there. Write down the pin numbers on a piece of paper and start testing each one. Someone else here may have more knowledge about these kind of LCDs, but with methodical testing you can map all the pins eventually. I usually just toss them because it's so much easier to use standard Hitachi type units.
     
    Last edited: May 10, 2009
  17. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    Thanks for the advice on testing. Yeah, I know other types are easier to use, but this is what I have on hand, and since i have a pic designed to run these i figured that I may as well do it.
     
  18. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    The diode test mode on my meter doesn't seem to be enough to change the cells
     
  19. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    Did you try enough pins? I've tried similar displays on three different meters and had results. The hard part is finding a ground. Usually I pick one pin, attach the black lead to that one and strum the rest of the pins with the + pin till a pin lights up, if that doesn't work then I swap the lead and strum again. Doesn't take long till you start hitting segments.
     
    Last edited: May 10, 2009
  20. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    well, the reason that the diode test mode isnt working is still a mystery to me, but I got it to work pretty clearly with a 1.5v source. It seems to work if I just connect positive to one pin, then by strumming the other pins ever cell can be individually activated. They slowly fade unless i take the positive source and connect it directly to the same pin, then they shut off instantly even if it is still also connected to the ground pin. It works exactly the same with the positive and negative reversed. does this mean that from a micro controller I would just need to put that pin low (or high if that was opposite to the base pin) to display, and then set the pin high (or low) to clear?
     
  21. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    I'm not too familiar with actually controlling these kinds of LCD's, like I said I usually toss them in favor of line displays with built in controllers. They're just too much of a hassle for me to want to learn.
     

Share This Page