The motor direction is controlled by buttons connected to ports A4 and A5. Pushing the button changes the direction rotation of the corresponding motor. Releasing a button returns the motor direction to its original state. Both motors run from a single PWM controlled by the pot. Moving the pot tip towards its upper end on the schematic leads to increasing the rotation speed.
To control the motor speed we use PWM as in the previous experiments. The PIC reads the voltage coming out of the pot, which is in the range 0..5V, and redirects it to a built-in ADC with a 10-bit resolution. In this case, however, its two lower bits are ignored. The range of ADC values (0..255) is send directly to the PWM duty cycle ratio control register. This way we get an 8-bit PWM resolution. The PWM period is set to 244Hz.
Schematic | Layout | |
The main part of the program is an endless loop. At each iteration of this loop we read the ADC value and the buttons stati. The input ports A4 and A5 have weak pull-ups enabled. This results in the logical 1 value at these inputs if the buttons are not pushed. Pushing a button modifies this value to 0 and this is used to modify the direction of the corresponding motor. The direction is modified by complementing the corresponding pair of outputs RC3, RC4 or RC1, RC2. The complementing changes the voltage signs on the motor pins.
Note that in this implementation the motor speed is the same, since they are controlled by a single PWM. It is important to know that PWM runs in its own thread and releases the CPU for other operations. There is just one PWM thread in PIC16F684. Due to a difference of motor parameters, the control is not very reliable at very low voltages, as one or both motors might not rotate at all as they need a certain voltage to start. Furthermore, by the same reason the rotation speed at very low voltages might be different. This difference disappears as the pot tip moves about 1/4 of its range counted from the grounded end.
The code is as follows:
TITLE "pwm_mot2.asm" ; PWM control of two motors List P=PIC16F684, R=DEC INCLUDE "p16f684.inc" ; data segment CBLOCK 0x20 del ; variable used for delay temp ; local temp variable ENDC ; code segment PAGE __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT org 0 ; start program at the beginning of mem bcf STATUS, RP0 ; activate BANK 0 clrf PORTA ; initialize PORT A clrf PORTC ; initialize PORT C movlw 0x07 movwf CMCON0 ; comparators OFF bsf STATUS, RP0 ; change to BANK 1 bcf OPTION_REG ^ 0x80,7 ; enable pull-ups globally bsf WPUA ^ 0x80, 4 ; enable weak pull-us on A4,A5 bsf WPUA ^ 0x80, 5 ; ADC and PWM configuration movlw b'111001' movwf TRISA ^ 0x80 ; enable input on pins A0, A4, A5 clrf ANSEL ^ 0x80 incf ANSEL ^ 0x80, f ; configure A0 as analog input movlw b'01110000' ; set ADC Frc clock movwf ADCON1 ^ 0x80 movlw 0xFF movwf PR2 ^ 0x80 ; PWM period 244Hz clrf TRISC ^ 0x80 ; enable PORTC for output bcf STATUS, RP0 ; back to BANK 0 bsf ADCON0, 0 ; Left justify, Vdd Vref, AN0, On movlw 7 movwf T2CON ; enable Timer 2 with 1:16 prescaler movlw 0x0C ; enable single output PWM movwf CCP1CON loop movlw 20 movwf del call delay ; 20 msec delay bsf ADCON0, GO ; start ADC operation btfsc ADCON0, GO ; and wait for its completion goto $-1 movf ADRESH, w ; get higher 8 bits of ADC movwf CCPR1L ; setup PWM duty cycle ratio checkDir0 movlw b'01010' ; read the first button status btfsc PORTA, 4 xorlw b'11000' ; reverse direction for motor 0 checkDir1 ; do the same with the second motor btfsc PORTA, 5 xorlw b'00110' ; reverse direction for motor 1 movwf PORTC ; set up the motor directions goto loop ; endless loop ; procedures delay ; a delay for del milliseconds movlw 200 sublw 1 ; this loop takes 5us*200 = 1ms sublw 0 ; for PIC16F684 @ 4 Mhz btfss STATUS, Z goto $-3 decfsz del, f goto delay return end |
Download pwm_mot2.asm
Last modified:Mon, Jan 23, 2023.