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

Controlling Duty Cycle with pot via ADC(Assembly code PIC18f2550)

Status
Not open for further replies.

Cantafford

Member
Hey,

Basically what the title says. I'm generating some PWM signals from a pic microcontroller and feeding them to a DC motor. I'm using the ADC module to convert a continous voltage value to a digital one. Then I'm going to take this value and place it in the PIC's duty cycle register so I can vary the speed of the motor via the pot.

I wrote this code: I initialised the 2 LSB's of the duty cycle register with 0. The result of the ADC is left justified. My PWM will therefore have a resolution of 8 bits(the high byte of the ADC).

Code:
; PIC18F2550 Configuration Bit Settings

; ASM source line config statements

#include "p18F2550.inc"

; CONFIG1L
  CONFIG  PLLDIV = 1            ; PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
  CONFIG  CPUDIV = OSC1_PLL2    ; System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
  CONFIG  USBDIV = 1            ; USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)

; CONFIG1H
  CONFIG  FOSC = INTOSCIO_EC    ; Oscillator Selection bits (Internal oscillator, port function on RA6, EC used by USB (INTIO))
  CONFIG  FCMEN = OFF           ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
  CONFIG  IESO = OFF            ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

; CONFIG2L
  CONFIG  PWRT = OFF            ; Power-up Timer Enable bit (PWRT disabled)
  CONFIG  BOR = OFF             ; Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
  CONFIG  BORV = 3              ; Brown-out Reset Voltage bits (Minimum setting 2.05V)
  CONFIG  VREGEN = OFF          ; USB Voltage Regulator Enable bit (USB voltage regulator disabled)

; CONFIG2H
  CONFIG  WDT = OFF             ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
  CONFIG  WDTPS = 32768         ; Watchdog Timer Postscale Select bits (1:32768)

; CONFIG3H
  CONFIG  CCP2MX = ON           ; CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
  CONFIG  PBADEN = OFF          ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
  CONFIG  LPT1OSC = OFF         ; Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
  CONFIG  MCLRE = OFF           ; MCLR Pin Enable bit (RE3 input pin enabled; MCLR pin disabled)

; CONFIG4L
  CONFIG  STVREN = ON           ; Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
  CONFIG  LVP = ON              ; Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
  CONFIG  XINST = OFF           ; Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

; CONFIG5L
  CONFIG  CP0 = OFF             ; Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
  CONFIG  CP1 = OFF             ; Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
  CONFIG  CP2 = OFF             ; Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
  CONFIG  CP3 = OFF             ; Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)

; CONFIG5H
  CONFIG  CPB = OFF             ; Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
  CONFIG  CPD = OFF             ; Data EEPROM Code Protection bit (Data EEPROM is not code-protected)

; CONFIG6L
  CONFIG  WRT0 = OFF            ; Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
  CONFIG  WRT1 = OFF            ; Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
  CONFIG  WRT2 = OFF            ; Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
  CONFIG  WRT3 = OFF            ; Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)

; CONFIG6H
  CONFIG  WRTC = OFF            ; Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
  CONFIG  WRTB = OFF            ; Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
  CONFIG  WRTD = OFF            ; Data EEPROM Write Protection bit (Data EEPROM is not write-protected)

; CONFIG7L
  CONFIG  EBTR0 = OFF           ; Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
  CONFIG  EBTR1 = OFF           ; Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
  CONFIG  EBTR2 = OFF           ; Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
  CONFIG  EBTR3 = OFF           ; Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
 
ES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    START                   ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

MAIN_PROG CODE                      ; let linker place main program

START
   
    call _PWM_Init
    call _ADC_Init
 
    loop                          ; loop forever
 
    call _ADC_Conversion ;get value from AN0 and put it in PWM register(CCPR1L)
 
    goto loop
 
_PWM_Init
    BANKSEL OSCCON       ;internal 8Mhz oscillator
    movlw b'01110111'
    movwf OSCCON
 
    movlw b'01010010'
    movwf PR2
 
    movlw b'00000111'
    movwf T2CON
 
    BANKSEL CCP1CON ; PWM mode selected. LSBs of PWM duty cycle = 0
    bsf CCP1CON, 3
    bsf CCP1CON, 2
    bcf CCP1CON, 4
    bcf CCP1CON, 5
 
    BANKSEL TRISC
    clrf TRISC
    bsf LATC, 0 ;direction for the motor
    bcf LATC, 1
return
 
_ADC_Init
    bsf TRISA, 0 ;AN0 made as input
 
    BANKSEL ADCON0
    movlw b'00000001' ; select chanel 0, turn on ADC
    movwf ADCON0
 
    movlw b'00001110' ;ref select, AN0 made analog
    movwf ADCON1
 
    movlw b'00001000' ;Fosc/2, result is left justified, 2 TAD
    movwf ADCON2
return
 
_ADC_Conversion
    bsf ADCON0, 1 ;start conversion by setting GODONE bit
    btfsc ADCON0, 1 ;once the GODONE bit is cleared continue
    goto _ADC_Conversion
    MOVFF ADRESH, CCPR1L ; take the value from the pot and put it in the PWM register
return

    END
This is the schematic in proteus:


When I run the code my motor goes full speed no matter what the position of the pot is. It's the first time I try to do this in assembly. I'm not sure if I moved the value from the ADC conversion to the CCPR1L(duty cycle register).
Code:
MOVFF ADRESH, CCPR1L ; take the value from the pot and put it in the PWM register
Also in ISIS I get the following warning:
"ADC conversion clock period violates the required TAD time"
Does this mean I have to insert a delay somewhere in the code? Or increase the number of TADs?
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Also in ISIS I get the following warning:
"ADC conversion clock period violates the required TAD time"
Does this mean I have to insert a delay somewhere in the code? Or increase the number of TADs?
No... ISIS is just complaining that the impedance into the pin doesn't match the "datasheet"..

If you are reading a voltage from a pot, turned by a human... Then the samples will be fine...

I love the word "Violates" .... Arrgghh--- run for the hills!!

A tiny lesson in PWM... I have mentioned this to you before.... PR2 = 82... The ADC will yield 0 ~ 255.. So the PWM is on MAX most of the time.. Does it change when the pot is at zero??
 

Cantafford

Member
No... ISIS is just complaining that the impedance into the pin doesn't match the "datasheet"..

If you are reading a voltage from a pot, turned by a human... Then the samples will be fine...

I love the word "Violates" .... Arrgghh--- run for the hills!!

A tiny lesson in PWM... I have mentioned this to you before.... PR2 = 82... The ADC will yield 0 ~ 255.. So the PWM is on MAX most of the time.. Does it change when the pot is at zero??
No still full speed.
 

Cantafford

Member
Not sure if this is your issue, but you should not keep setting the ADC GO bit like you do.

Change this:


To this:
If I replace with "goto $" the program behaves the same. If I replace with "goto $-1" I get an error :(

I do not think that is the problem in my code.
I think my problem lies somewhere here:
Code:
MOVFF ADRESH, CCPR1L ; take the value from the pot and put it in the PWM register
In _ADC_Conversion label I'm in bank1. But then I need to move the result from the ADC's register(which is in bank1) to bank2(the pwm duty cycle register). So I'm not sure if I have to select the new bank before or after copying that value to the pwm duty cycle register. I'm not sure how I have to proceed there but I have a feeling is there where I'm doing something wrong.

Also my teacher says I should never use "goto $" as it's bad practice. He explained why but I didn't really understand what he said. He has an ambiguous way of explaining things. Why is that bad practice?
 

Cantafford

Member
I have modified the _ADC_Conversion label to:

Code:
_ADC_Conversion
    BANKSEL ADCON0
    bsf ADCON0, 1 ;start conversion by setting GODONE bit
    btfsc ADCON0, 1 ;once the GODONE bit is cleared continue
    goto _ADC_Conversion
    BANKSEL CCPR1L
    MOVFF ADRESH, CCPR1L ; take the value from the pot and put it in the PWM register
return
Basically added the 2 BANKSELs.
Now it all works fine in the 0-33% range. This means while the pot is not over 33% of it's maximum position the dc motor can be controlled fine(it's speed respects the position of the pot). However if I move the pot past 33% position the DC motor will go to 0 speed and stay there no matter if I try to move the pot up again...

Also if I start the simulation while the pot is over it's 33% of it's max position the motor will run full speed and I won't be able to control the speed with the pot anymore(it will stay 100% all the time).
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Yep... I found this to be true...

This may be a bug in ISIS.... The pic18f25xx has a PWM shutdown on CCP1... It seems as if the PWM will never restart.... The bits that control the autoshutdown aren't even available on that device..

According to the datasheet the 28 pin devices do not have ECCP modules, but then it said that CCP1 is ECCP on that device.... I think that ISIS have an issue.

Two things... either make you variable so it cannot exceed PR2 or make PR2 0xFF..
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top