3 Attachment(s)
L298N Motor Driver using pwm code not working..
Hi, I know I have unfinished topic in another thread, but I'm still waiting some parts to come, so I decided to move on to my simple mobile robot structure. The sensors mentioned from the other thread are going to be placed on this three wheeled robot. But I hit another brick wall. I've been losing my head since this morning..it's 2Am now already :(. I hope anybody can help me out..I'm having trouble driving the motors using PWM. When not using the PWM, motors work great...please see image\schematic below.
Attachment 6682
My setup
Attachment 6684
My codes:
Code:
Define OSC 20
ANSEL=%00000000
ANSELH=%00000000
TRISC = 0
PORTC = 0
TRISD = 0
PORTD = 0
MainLoop:
PortD.0 =1
PortD.1 =0
PortD.2 =1
PortD.3= 0
PortC.4 ,127, 100
PortC.5 ,127, 100
Goto MainLoop
Can any one spot what I'm doing wrong...I appreciate any input.
Kind regards,
tacbanon
Re: L298N Motor Driver using pwm code not working..
That code looks just wrong.
You set four outputs on PortD while the schematic shows PortC.
Then you seems to missing the actual PWM statement, and if you meant to PWM the Enable pins you have those too on the wrong pins.
I'm surprised if that code even compiles.
/Henrik.
1 Attachment(s)
Re: L298N Motor Driver using pwm code not working..
Hi Henrik,
My bad, uploaded the wrong image(must be very tired last night)
[ATTACH=CONFIG]6686[/ATTACH
Thanks for the replying...I will try it today and post here my output.
Quote:
and if you meant to PWM the Enable pins you have those too on the wrong pins.
..aren't pin5 and pin6 the PWM pins on JP6?
/tacbanon
Re: L298N Motor Driver using pwm code not working..
Hi, kindly check if this should be the right pins assignment.
PortD.0 to input3 of l298
PortD.1 to input4 of l28
PortC.0 to enable of l298
Quote:
by henrik: I'm surprised if that code even compiles.
Really sorry..next time I will double check before uploading.:o
Code:
PWM PORTD.0, 127,100
PWM PORTD.1, 127,100
PortC.0 = 1
Hope I'm close...
/tacbanon
Re: L298N Motor Driver using pwm code not working..
Concentrate on one bridge and motor to begin with, when you have that working apply the same procedure to the second bridge/motor.
Bridge 1 is controlled In1, In2 and ENA - in your case (according to your latest schematic) PortD.0, PortD.1 and PortC.4 respectively.
To drive the motor forward you drive PortD.0 high, PortD.1 low and apply the PWM signal to PortC.4
Code:
PortD.0 = 1
PortD.1 = 0
Main:
For i = 0 to 200 ' Ramp up.
PWM PortC.4, i, 10
NEXT
For i = 200 to 0 Step -1 ' Ramp down.
PWM PortC.4, i, 10
NEXT
Pause 500
Goto Main
According to the photo of the board there are a jumper for each bridge which says Remove jumper for PWM - did you do that? If you didn't the EN-pins are tied high and will short your PWM signal to the boards Vcc.
/Henrik.
Re: L298N Motor Driver using pwm code not working..
Thank you Henrik for saving me hours of time just to make it ...I got it :D finally! I will try to add the other bridge, then post here my result.
regards,
tacbanon
1 Attachment(s)
Imrproving motor control in line follower application.
Hi, I did manage to add the other motor, right now I made as a line tracker robot :). Not very well on the curves yet and a little slow..hope you can look onto my codes and might able to improve the performance..
Attachment 6688
Code:
DEFINE osc 4
ANSEL = %00000111 ' Make AN0-AN7 Analog
ANSELH= %00000000 ' Make AN8-AN13 digital
TRISA = %00111111
ADCON1 = %00001001
TRISC = 0
TRISD = 0
TRISB = 0
;-------------Variables
senCenter var byte
senRight var byte
senLeft var byte
i var word
i = 0
PORTD.0 = 1 ' In1
PORTD.1 = 0 ' In2
PORTB.0 = 1 ' In3
PORTB.1 = 0 ' In4
; PORTC.4 PWM Signal
loop1:
Adcin 0, senCenter
Adcin 1, senRight
Adcin 2, senLeft
;Serout2 PORTD.2, 84, [$1B,$45,Dec senCenter," ", DEc senRight," ",Dec senLeft]
;------------------------Select options seen by the sensors
IF senCenter > 150 and senRight > 150 then
Gosub movExtRight
Endif
IF senCenter > 150 and senLeft > 150 then
Gosub movExtLeft
Endif
IF senCenter > 150 then
;Serout2 PORTD.2, 84, [$1B,$45]
;Serout2 PORTD.2, 84, [$D," Center"]
gosub movForward
Endif
IF senRight > 150 then
;Serout2 PORTD.2, 84, [$1B,$45]
;Serout2 PORTD.2, 84, [$D,"Rigth"]
gosub movRight
Endif
IF senLeft > 150 then
;Serout2 PORTD.2, 84, [$1B,$45]
;Serout2 PORTD.2, 84, [$D," Left"]
gosub movLeft
Endif
;------------------------
;gosub movForward
GOTO loop1 ' Do it forever
END
movForward: ' forward
PORTD.0 = 1 ' In1
PORTD.1 = 0 ' In2
PORTB.0 = 1 ' In3
PORTB.1 = 0 ' In4
PWM PORTC.4 ,200,10
PWM PORTC.5 ,200,10
return
movExtRight: ' turn more to the right
PWM PORTC.4 ,50,10
PWM PORTC.5 ,200,10
return
movRight: ' short right
PWM PORTC.4 ,100,10
PWM PORTC.5 ,200,10
return
movLeft: ' short left
PWM PORTC.4 ,200,10
PWM PORTC.5 ,100,10
return
movExtLeft: ' turn more to the left
PWM PORTC.4 ,200,10
PWM PORTC.5 ,50,10
return
senLost: ' Getback no line detected
PORTD.0 = 0 ' In1
PORTD.1 = 1 ' In2
PORTB.0 = 0 ' In3
PORTB.1 = 1 ' In4
PWM PORTC.4 ,200,5
PWM PORTC.5 ,200,5
pause 50
return
Thanks in advance,
tacbanon
Re: L298N Motor Driver using pwm code not working..
Since you're using the 16F887 which has two CCP-modules the first thing I'd do is the rewire the thing so that the EN-pins of the L298N are connected to PortC.1 and PortC.2 and use HPWM instead.
That way the PWM generation is handled in the background, by the CCP-modules (instead of tying up the processor) and you only need to update it when you want to change the speed. Your program gets a lot of time to do other things.
Then I'd probably set up a timer interrupt to trip every 25ms or something. In the ISR I'd read the sensors and set the PWM dutycycles accordingly.
I can not make it stay on the line
Hi, I'm back...I got the HPWM working and also the timer. But I can never make the robot stay on track/line :confused:. Probably my setup is not right or something...kindly check my codes, hoping you can help me out spot what I'm doing wrong.
Code:
DEFINE OSC 4
ANSEL = %00000000 ' Make AN0-AN7 Digital
ANSELH= %00000000 ' Make AN8-AN13 digital
;--------- Setup Interrupt--------------------------
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _CheckSensors, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
;--------------------------------------------------
T1CON = %00100001 ; 00110001 Prescaler = 8, TMR1ON
@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
;--Setting HPWM
TRISC.1 = 0 'Set CPP2 to PWM output
TRISC.2 = 0 'Set CPP1 to PWM output
CCP1CON = %0001100 ' Set CCP1 to PWM, Active High
CCP2CON = %0001100 ' Set CCP1 to PWM, Active High
TRISA = %00111111 ' did not anymore use this for now
ADCON1 = %00001001
TRISC = 0
TRISD = 0
TRISB = %10000111 ' 0-2 for sensors
PortB = %00000000 ' Reset PortB
OPTION_REG = $7f
;--Init variables
i var Byte
i = 0 ; 200
;-- wheel on forward
PORTD.0 = 1 ' In1
PORTD.1 = 0 ' In2
PORTD.2 = 1 ' In3
PORTD.3 = 0 ' In4
;-------------------Speed of motor--
Gear var byte[10]
;--Set allowable speed---
Gear[1] = 0
Gear[2] = 75 ' start slow roll
Gear[3] = 80
pause 2000
i = 2
MainLoop:
;pause 100
; Start rolling
HPWM 1 ,Gear[i],10
HPWM 2 ,Gear[i],10
GOTO Mainloop ' Do it forever
END
'---[TMR1 - interrupt handler]--------------------------------------------------
CheckSensors:
if PortB.0 = 1 and PortB.2 = 0 then ' Left sensor
HPWM 1 ,Gear[3],10
HPWM 2 ,Gear[2],10
pause 20
;Serout2 PORTB.6, 84, [$D,"Right "]
ELSE
if PortB.1 = 1 and PortB.2 = 0 then ' Right sensor
HPWM 1 ,Gear[2],10
HPWM 2 ,Gear[3],10
;Serout2 PORTB.6, 84, [$D," Left"]
pause 20
ELSE
if PortB.2 = 1 and PortB.0 = 0 and PortB.1 = 0 then ' Center sensor
i = i + 1
if i > 2 then
i = 3
ENdif
;Serout2 PORTB.6, 84, [$D," Center "]
ELSE
;-------------------More than 1 sensors detected
if PortB.0 = 1 and PortB.2 = 1 then ' Left and Center sensor
HPWM 1 ,Gear[3],10
HPWM 2 ,Gear[3],10
;Serout2 PORTB.6, 84, [$D,"Right-Center "]
Else
if PortB.1 = 1 and PortB.2 = 1 then ' Right and Center sensor
HPWM 1 ,Gear[3],10
HPWM 2 ,Gear[3],10
Serout2 PORTB.6, 84, [$D,"Center-Left "]
Else
if PortB.0 = 0 and PortB.2 = 0 and PortB.1 = 0 then ' Can't see no line
;HPWM 1 ,Gear[0],10
;HPWM 2 ,Gear[1],10
Serout2 PORTB.6, 84, [$D,"No more line? "]
pause 50
ELSE
Serout2 PORTB.6, 84, [$D,"Error??? "] ' Others
ENdif:ENDIF:ENDIF:ENDIF:ENDIF:ENDIF
@ INT_RETURN
Thank you in advance,
tacbanon
Re: L298N Motor Driver using pwm code not working..
Hi,
I don't really follow your coding but you have a main loop which constantly (I mean thousands of times per second) keeps setting the dutycycle to some value. When the interrupt fires, decide which way to turn (if any) and set the dutycycle, don't change it the main loop. BTW, does 10Hz really work? Also, in your previous code I got the impression that the sensors were analog (you used ADCIN to read them) but now they are digital?
/Henrik.
EDIT: One more thing, you don't seem to reload the timer value in the ISR.
Since the timer is freerunning and generating an interrupt on overflow, with a prescaler of 8 and a 4MHz x-tal the interrupt frequency of 4000000/4/8/65536=1.9Hz, I think you need to run faster than that.
Re: L298N Motor Driver using pwm code not working..
Hi Henrik, thanks you for your comments..I guess I have to rearrange my codes.
Quote:
don't change it the main loop.
Does this mean I have to remove this in the main loop..
Code:
; Start rolling
HPWM 1 ,Gear[i],10
HPWM 2 ,Gear[i],10
and place it in a sub program?
I did remove the analog reading to digital because I thought it will better...don't you think so?
Regarding the timer, should this be the value T1CON = %00100001 ?
I really appreciate for answering my questions..not really all clear to me at this time but I hope I will learn some if not all.
BTW do you think it is best to have a fix speed instead of changing from time to time?
regards,
tacbanon
Re: L298N Motor Driver using pwm code not working..
Hi,
HPWM works in the background, once you tell it to output a certain dutycycle with a certain frequency it does that in hardware. There's no need to continously execute the HPWM commands like your doing in your main loop.
If you change the prescaler to 1:1 you'll get an interrupt every 65536us or around 15Hz, I'd try that as a starting point. If you need faster interrupt rate than that you need to preload the TMR1 register in the ISR so that it doesn't start from 0. If you load with 55536 there will be 10000 cycles (or 10000us in this case) untill the next interrupt.
I have no idea if analog or digital sensor is best. I don't even know what sensors you're using....
If you have two sensors, one on "each side" of the line then I think two speeds for each motor should do. Run both motor at the lower speed to go straight forward, increase the speed of one motor to turn. (Or do the oposite if you want).
Re: L298N Motor Driver using pwm code not working..
Hi, thanks...I will try your suggestions regarding the timer/interrupt implementation...but I still don't get what you meant HPWM working on the background...my question probably is how I can change the speed parameter if I needed?
speedR var byte
speedL var byte
speedR = 150
speedL = 150
pause 2000
HPWM 1 ,speedR,10 ' Right Wheel
HPWM 2 ,speedL,10 ' Left wheel
Mainloop:
speedR = 100 ' new value of speed
speedL = 150 '
Goto Mainloop
regards,
tacbanon
Re: L298N Motor Driver using pwm code not working..
Hi,
To change the speed you to execute the HPWM command. What I'm "objecting" against is this:
Code:
Main:
HPWM.....
HPWM.....
Goto Main
When you do it this your trying to update the PWM generator thousands of time per second. What happens when you update it faster then the frequency it's outputting? I don't know the answer.
In the ISR, determine what duty cycles to send to each motor and execute the HPWM command there. That way you'll update the speed once each interrupt instead of thousands of times per second.
/Henrik.
Re: L298N Motor Driver using pwm code not working..(Solved)
Hi Henrik...many thanks for the kindly explaination...appreciate it very much...got it now.
regards,
tacbanon