Continue to Site

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.

  • 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.

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

Status
Not open for further replies.
No, your mistake. I was talking about the so-called 'PPM' signal used to modulate the RF signal.

For a constant frame rate, the signal going to the servo is PWM.

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:
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.
 
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).
 
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).

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.
 
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.
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.
I'm working on an idea for a remote controlled device that could be simplified greatly if i can get a chip that can measure the pulse width of 3 and produce 3 pwm signals simultaniously, better yet measure 3 and output 6, I'm newer at this so if that's ridiculous forgive my ignorance.
 
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.
 
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.
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.
 
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:
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
 
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:
; 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
 
And here are the two include files:

Code:
	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:
	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
 
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.

**broken link removed**
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"
 
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:
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.
 
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:
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?
 
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.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top