How to Implement 25us Delays in PIC16F84A PWM Code?

AI Thread Summary
The discussion focuses on implementing 25 microsecond delays in PWM code for a PIC16F84A to control a DC motor's speed. Participants suggest using a state machine approach, where the state is read from PortA and determines the motor's on/off timing based on specific delay patterns. A tight in-line delay loop is recommended for achieving the 25 microsecond delay efficiently, as using a timer may not be effective for such short intervals. The code structure includes conditional checks for motor activation and appropriate delays based on the state. Overall, the conversation emphasizes the importance of precise timing and efficient coding practices for PWM control.
Noob of the Maths
Messages
52
Reaction score
6
Hello how are you :D

I have some problems with my code, which is to control the speed of a DC motor by pwm with the pic16f84A.

I already have the combinations and the diagram of the signals, but I still need to implement the part in bold.

How would the delays be implemented so that they have 25 us, 50 us, 75 us according to the diagram? I do not understand that part ;(
The time per cycle is 100 microseconds

Captura de Pantalla 2022-05-16 a la(s) 17.50.57.png
Captura de Pantalla 2022-05-16 a la(s) 17.51.32.png
 
Technology news on Phys.org
If this is free running code, without interrupts, then three of the states will need two delay loops.
Declare a register called State, read RA into state
State = State AND 0h07 mask high five, keep only three lowest bits
There are 5 cases.
If State(bit2) = 0 then turn off; wait 100u; end
If State = 00 then turn on; wait 25; turn off; wait 75; end
If State = 01 then turn on; wait 50; turn off; wait 50; end
If State = 10 then turn on; wait 75; turn off; wait 25; end
If State = 11 then turn on; wait 100u; (turn off?); end
Is PortB, bit 0 the output to the motor?
 
Baluncore said:
If this is free running code, without interrupts, then three of the states will need two delay loops.
Declare a register called State, read RA into state
State = State AND 0h07 mask high five, keep only three lowest bits
There are 5 cases.
If State(bit2) = 0 then turn off; wait 100u; end
If State = 00 then turn on; wait 25; turn off; wait 75; end
If State = 01 then turn on; wait 50; turn off; wait 50; end
If State = 10 then turn on; wait 75; turn off; wait 25; end
If State = 11 then turn on; wait 100u; (turn off?); end
Is PortB, bit 0 the output to the motor?
Oh, i now understand the times. Yes, the output to the motor can be any bit of the PortB.
 
I would write straight code with unconditional equal delays
Declare a register called State,
label Cycle; it will get back here every 100 usec
read PortA into state
State = State AND 0h07; mask high five, keep only three lowest bits
If state(bit2) = 1 then turn on motor
delay 25 usec
if state = 0b100 then turn off motor
delay 25 usec
if state = 0b101 then turn off motor
delay 25 usec
if state = 0b110 then turn off motor
delay 25 usec
turn off motor here only if needed?
Goto cycle
 
Baluncore said:
I would write straight code with unconditional equal delays
Declare a register called State,
label Cycle; it will get back here every 100 usec
read PortA into state
State = State AND 0h07; mask high five, keep only three lowest bits
If state(bit2) = 1 then turn on motor
delay 25 usec
if state = 0b100 then turn off motor
delay 25 usec
if state = 0b101 then turn off motor
delay 25 usec
if state = 0b110 then turn off motor
delay 25 usec
turn off motor here only if needed?
Goto cycle
The code its like this?
 

Attachments

  • Captura de Pantalla 2022-05-17 a la(s) 7.27.33.png
    Captura de Pantalla 2022-05-17 a la(s) 7.27.33.png
    36 KB · Views: 124
You did not understand the straight code with unconditional equal delays. There are 4 delays of 25 usec in the loop. The total delay is therefore the loop period of 100 usec. If active, the motor is turned on at the start, then turned off after the appropriate delay, depending on the state of portA.

There are a couple of tricks needed to keep it compact. Also, the 50% state might better be done with [on-off-on-off], rather than [on-on-off-off].

I will see if I can write some PIC16F84 code tomorrow.
 
Attached is untested code for 100 usec state machine loop.
You will need to make the delay 25 usec routine.
 

Attachments

  • Like
Likes Noob of the Maths
@Noob of the Maths

25 usec is probably too short to be done efficiently with a timer.
An in-line delay might be more appropriate, then you can trim the number of cycles.
With a 4 MHz clock the instruction time is 1 usec.

Cblock ; assign delay variable to next available register in file
count
endc

; this is the tight in-line loop that does not use a timer
; Delay(25) start with a number that will make up to the 25 usec
movlw 12; adjust the start count
movwf count
decfsz count, f
goto $-1
; count is now zero, pad with a NOP if you need 1 usec more

I have been thinking about the state conversion.

Your table of 3 bit codes;
0 x x = 0%
1 0 0 = 25%
1 0 1 = 50%
1 1 0 = 75%
1 1 1 = 100%
Can be converted to 4 columns by duplicating the middle column, onto the right;
0 x x = 0 x x x = 0%
1 0 0 = 1 0 0 0 = 25%
1 0 1 = 1 0 1 0 = 50%
1 1 0 = 1 1 0 1 = 75%
1 1 1 = 1 1 1 1 = 100%
Notice how these 4 bits are now arranged so the number of bits set, is correct for the duty cycle.
To generate the motor PWM you only need output those 3 bits at the appropriate 4 times.
It is simplest to select PortB, bit 1, as the motor output.

; The code then becomes something like this
Loop
movf PortA,w ; get state
movwf pattern ; save pattern
btfss pattern,2 ; test motor on/off
clf pattern ; if motor off

; Copy bit(2) to output
rrf pattern,w
movwf PortB
Delay(25)

; Copy bit(1) to output
movf pattern,w
movwf PortB
Delay(25)

Copy bit(0) to output
rlf pattern,w
movwf PortB
Delay(25)

; Copy bit(1) to output
movf pattern,w
movwf PortB
Delay(25)

Goto Loop
 
Back
Top