Thank you Henrik for saving me hours of time just to make it ...I got itfinally! I will try to add the other bridge, then post here my result.
regards,
tacbanon
Thank you Henrik for saving me hours of time just to make it ...I got itfinally! I will try to add the other bridge, then post here my result.
regards,
tacbanon
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..
Thanks in advance,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
tacbanon
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.
Hi, I'm back...I got the HPWM working and also the timer. But I can never make the robot stay on track/line. Probably my setup is not right or something...kindly check my codes, hoping you can help me out spot what I'm doing wrong.
Thank you in advance,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
tacbanon
Last edited by tacbanon; - 29th September 2012 at 01:52.
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.
Last edited by HenrikOlsson; - 29th September 2012 at 10:51.
Hi Henrik, thanks you for your comments..I guess I have to rearrange my codes.
Does this mean I have to remove this in the main loop..don't change it the main loop.
and place it in a sub program?Code:; Start rolling HPWM 1 ,Gear[i],10 HPWM 2 ,Gear[i],10
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
Last edited by tacbanon; - 29th September 2012 at 11:27.
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).
Bookmarks