Shop OBEX P1 Docs P2 Docs Learn Events
Replacing a PWM,Dir Hbridge with a -100, 0, 100 duty cycle Hbridge for Dance bot — Parallax Forums

Replacing a PWM,Dir Hbridge with a -100, 0, 100 duty cycle Hbridge for Dance bot

crazyrobotgirlcrazyrobotgirl Posts: 32
edited 2012-12-07 19:47 in Propeller 1
I am trying to implement my H-Bridge in place of Hannos dance bot hbridge. His H-bridge uses a two wire connection (PWM,and Dir), while mine uses a three wire connection ( An enable pin , forward pin , and forward inverse pin). I found this object http://obex.parallax.com/objects/455/ on the object exchange Saturday after blowing one of my LMD18200 hbridge. I spent the week trying to do it myself with no luck. I have tested the object with my hbridge and motors and everything is working fine.
If anyone has any idea on how to do this please help.
 Hannos H-bridge{*******************************************************
* (C) 2010 HannoWare.com                               *
* Drive 2 motors with h-bridge and read encoder        *
* AppletImage=motor.gif                                *
********************************************************}
CON
  _clkmode        = xtal1 + pll16x
  _xinfreq        = 5_000_000
  MAXSPEED=4000
  motorUpdateHz=200
  'pins for h-bridge: 3,4,26,27
  'pins for encoder: 12,13
  m1Dir= |<3
  m1Pwm= |<4
  m2Dir= |<26
  m2Pwm= |<27
var
  long pwm[6]  'structure populated by spin code to set motor direction
obj
  vp : "Conduit"
  qs:"QuickSample"
pub Main|mvel,pos[2],cmd[2],join,but,frame[400],lastP,ncnt
  {testing harness for driving/measuring motors
    mvel=motor velocity- only monitoring one encoder
    pos=position for two motors
    cmd=command power for two motors
    join=set to 1 by viewport to tell both motors to move at same speed
    but=button clicked in viewport to trigger a speed test
    frame=used by quicksample to measure the io port
    lastp= last position- used to calculate mvel
    ncnt= next cnt, used to control time of loop}
  
  vp.register(qs.sampleINA(@frame,1)) 'sample INA with 1 cog up to 20Mhz
  vp.config(string("var:io(bits=[4m1p,3m1r,27m2p,26m2r,12enc,13enc]),mvel,pos1,pos2,m1(min=-5000,max=5000),m2(min=-5000,max=5000),join,but"))
  vp.config(string("lsa:view=io,timescale=1ms,trigger=io[30]r")) 
  vp.config(string("dso:view=[mvel,pos1,pos2,m1,m2],timescale=1s"))
  vp.config(string("edit:join(mode=switch),m1(mode=scroll),m2(mode=scroll)"))
  vp.config(string("start:dso"))
  vp.share(@mvel,@but)
  start(@pos)
  ncnt:=cnt
  if 0 'set to 1 to do speed test
    repeat
      if but
        ncnt:=cnt
        pos~
        lastP~
        repeat motorUpdatehz
          Update(cmd[0],cmd[0])
          waitcnt(ncnt+=clkfreq/motorUpdateHz)
          mvel:=pos-lastP
          lastP:=pos
        Update(0,0)        
        but~ 
  repeat
    if join
      Update(cmd[0],cmd[0])
    else
      Update(cmd[0],cmd[1])      
    mvel:=pos-lastP
    lastP:=pos
    waitcnt(ncnt+=clkfreq/motorUpdateHz)'}}  
pub Start(posPtr)
'starts 1 encoder cog and 1 motor cog.  initializes positions
  setupEncoder(posPtr)
  setupMotor
  long[posPtr]~
  long[posPtr+1]~
pub Update(speed,speed2)|p0,p2,t
'updates motor control with desired speed
  p0:=m1pwm+m2pwm
  if speed>0
    p0+=m1dir
  if speed2>0
    p0+=m2dir
  pwm[0]:=p0    
  speed:= (||speed) <#MAXSPEED
  speed2:= (||speed2) <#MAXSPEED
  if speed > speed2
    p0-=m2pwm
    pwm[1]:=(speed2)+5  '2505
    pwm[3]:=(speed-speed2)+5 '2505
    pwm[5]:=5+(5000-speed)   '15 
  else
    p0-=m1pwm
    pwm[1]:=(speed)+5
    pwm[3]:=(speed2-speed)+5
    pwm[5]:=5+(5000-speed2)
  pwm[2]:=p0
  pwm[4]:=0   
  
pub setupMotor
  pwm[1]:=5
  pwm[3]:=5
  pwm[5]:=5
  diraV:=m1Dir|m1Pwm|m2Dir|m2Pwm
  andV:=!diraV
  cognew(@doPWM,@pwm)
  
pub setupEncoder(posPtr)
  cognew(@count,posPtr)
dat
        org
count
        mov m2w,par
        add m2w,#4 
        mov  :t,ina              'get ina- 1011
:loop  ' 21 instr= 80 cnts=1Ms/sec
        and :t,mAEnc             't shows before flank, what A bit where
        waitpne :t,mAEnc         'wait for encoder A bits to change
        mov :t1,ina                
        and :t1,mABEnc           't1 shows after flank, what AB bits are 
        mov :t2,:t1
        and :t2,mAEnc
        xor :t2,:t               ' t2 shows which A bits changed
        mov :t,:t1               ' get t ready for next measurement
        shr :t2,#12
        rcr :t2,#1   wc          ' check if A on motor 1 changed        
  if_nc shr :t1,#14               ' leave both t2, t1 shifted if take jump
  if_nc jmp #:doM2                '
        shr :t1,#12
        rcr :t1,#1   wc          ' check if A=1
  if_nc shr :t1,#1
  if_nc jmp #:doM2      
        rcr :t1,#1   wc          ' check fwd/bkw on motor 1
        rdlong m1Cnt,par'added
  if_c add m1Cnt,#1
  if_nc  sub m1Cnt,#1
        wrlong m1Cnt,par         
        'ready to do motor 2, t1 shifted 14, t2 shifted 13
:doM2
        shr :t2,#9
        rcr :t2,#1   wc          ' check if A on motor 2 changed
  if_nc jmp #:loop
        shr :t1,#8
        rcr :t1,#1   wc          ' check if a=1
  if_nc jmp #:loop
        rcr :t1,#1    wc          ' check if fwd/bkw on motor 2
        rdlong m2cnt,m2w   'added
  if_nc add m2Cnt,#1
  if_c  sub m2Cnt,#1         
        wrlong m2Cnt,m2w               
        jmp #:loop
:t2     long 1      
:t1     long 1        
:t      long 1
m2W     long 1
mAEnc   long 00_0000_0001_0000_0000_0000 '12
mABEnc  long 00_0000_0011_0000_0000_0000' 12,13 '00011
m1Cnt   long 0
m2Cnt   long 0
' outputs pwm to motors
' uses pwm structure to get bit values and duty cycles
        org
doPWM   or dira,dirav
 loop   mov ptr,par      
        mov :i,#3             
:duty   rdlong orV,ptr   'get value to or
        add ptr,#4
        mov :t,outa
        rdlong timeV,ptr  'get wait
        add ptr,#4
        and :t,andV
        or :t,orV
        mov outa,:t
        add timeV,cnt
        waitcnt timeV,#0
        djnz :i,#:duty
        jmp #loop
:t      long 1
:i      long 1        
diraV   long 1
andV    long 1      
ptr     long 1
orV     long 1        
timeV   long 1

Comments

  • CircuitsoftCircuitsoft Posts: 1,166
    edited 2012-12-06 10:25
    attachment.php?attachmentid=78421&d=1297987572
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-12-06 10:44
    crg,

    As you know by now, indentation in part of Spin code. The forum software deleted extra spaces unless you use code tags as shown in the link Circuitsoft provided.

    It would help me figure out how to incorporate the other H-bridge driver in you balancing bot code if you archive the code you're using. In order to archive your code you need to first compile it and then in the Propeller Tool select 'File\Archive "file name"\project' which will create a zip file with all the objects used.

    Please include any other code you want us to look at as an attachment or as a link (as you did above to the OBEX code).

    I know I've modified H-bridges drivers to use different types on enable or direction pins.

    You mentioned in your PM you bot was balancing for a while. How long did it balance and could it keep upright if you gave it a little push? That's very cool to have had it balance at all.
  • crazyrobotgirlcrazyrobotgirl Posts: 32
    edited 2012-12-06 12:46
    It balanced for a good bit. I was able to push it back and forth while it kept its balance. I decided to do a test to see if I could get it to balance while I work on a program to controll it.
    but someone let the dog in and it attacked the robot. Blowing the unprotected LMD18200 h bridge.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-12-07 01:26
    I don't recall ever seeing PWM code like before (not that I've seen a whole lot). It's very interesting.

    Hanno breaks the time of the PASM driver into three sections.

    The first section is when only one motor is on (the one with a faster speed command).

    The second section is when both motors are on at the same time.

    The final section of time is the time when both motors are off.

    Hanno uses a mask to set the H-bridge control pins high or low. It wasn't very hard to modify his code to add the additional two control pins.

    Here's the modified "CON" section of the code. This code replaces the original "CON" section.
    CON
      _clkmode        = xtal1 + pll16x
      _xinfreq        = 5_000_000
      MAXSPEED=4000
      motorUpdateHz=200
      'pins for h-bridge: 3,4,26,27
      'pins for encoder: 12,13
      forward1 = |< 3  ' change to match forward pin on H-bridge
      forward2 = |< 26 ' change to match forward pin on H-bridge
      backward1 = |< 5  ' change to match backward pin on H-bridge
      backward2 = |< 25 ' change to match backward pin on H-bridge
      'm1Dir= |< 3
      m1Pwm= |<4
      'm2Dir= |<26
      m2Pwm= |<27
    

    I added pins P5 and P25. Just change these numbers to match the pins you're using. Remember not to use P30 or P31 since the communication object uses those pins. It's also a good idea not to use P28 and P29 for things other than I2C devices (EEPROM, real time clock, etc.)

    I also needed to change the "setupMotor" section in order to pass the new pin mask to the PASM driver. Here's the new "setupMotor" method (this replaces the previous "setupMotor" method.
    pub setupMotor
      pwm[1]:=5
      pwm[3]:=5
      pwm[5]:=5
      diraV:=forward1|forward2|backward1|backward2|m1Pwm|m2Pwm
      andV:=!diraV
      cognew(@doPWM,@pwm)
      
    

    I found it interesting that the PASM portion of the driver didn't need to be changed. The biggest changes were made to the "update" method. Here's the new "update" method.
    pub Update(speed,speed2)|p0,p2,t
    'updates motor control with desired speed
      p0:=m1pwm+m2pwm               ' combined PWM pin mask
      if speed>0
        p0+=forward1                ' if #1 positive speed add direction pin to mask
      else
        p0+=backward1
      if speed2>0
        p0+=forward2                ' if #2 positive speed add direction pin to mask
      else
        p0+=backward2
      pwm[0]:=p0                    ' set both motors on mask to where the PASM portion
                                    ' can read it
      speed:= (||speed) <#MAXSPEED
      speed2:= (||speed2) <#MAXSPEED
      if speed > speed2             ' if motor #1 should be on longer than motor #2
        p0-=m2pwm                   ' mask with motor #1 off
        pwm[1]:=(speed2)+5  '2505   ' time both motor on
        pwm[3]:=(speed-speed2)+5 '2505  ' time while on motor #1 is on
        pwm[5]:=5+(5000-speed)   '15  ' both motors off time
      else
        p0-=m1pwm
        pwm[1]:=(speed)+5
        pwm[3]:=(speed2-speed)+5
        pwm[5]:=5+(5000-speed2)
      pwm[2]:=p0
      pwm[4]:=0   
      
    

    Since I don't have the objects this program uses handy, I wasn't able to test compile it.

    In my ealier post I gave instructions on how to archive your program. It will help us (myself and other who may help in the future) if you use the archive feature so we can be sure we have all the objects needed. (Don't sweat it this time. From your PMs, it sounds like you've been busy at work.)

    Attaching code as a file has the advantage of not having errors introduced by the forum software. For example the percent signs for "mAEnc" and "mBAEnc" were removed by the forum software in your earlier post (the percent sign is a common glitch).

    I've attached the Spin file for the modified program. Hopefully it does the trick.

    I'm pretty excited to have learned these new tricks from Hanno. I think I can reclaim one of the cogs in my Mecanum wheeled robot by using Hanno's PWM technique. Instead of breaking the time into three pieces for two wheels, I can break the time into five pieces and control four motors/wheels.

    Let us know how your robots doing. It would be great to see some video of it in action.
  • crazyrobotgirlcrazyrobotgirl Posts: 32
    edited 2012-12-07 09:41
    Thank you Duane,

    I went over the code while drinking my joe, and realized I was somewhat close. But not close enough.
    I will post videos as soon as possible. Duane I am sure others will want to build a bot with what you done.
    Hanno did an awsome job putting it together. One of the other problems I had was the gyro. The GWS PG-03. For some reason out of the box it did not work. Others have had that problem
    I was able to replace it with another gyro (PZ-200, heli gyro) and it workes fine. I plan to replace the hobby gyro with a gyro from the parallax store. That way all will be able to build a dance bot
    with parallax parts.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-12-07 10:41
    I plan to replace the hobby gyro with a gyro from the parallax store.

    This should be possible but not necessarily simple. I don't think any of the gyros Parallax sells use the same signal protocol as an RC gyro.

    Let me know if the H-bridge program works or not. I haven't even compiled it much less tested it.
  • crazyrobotgirlcrazyrobotgirl Posts: 32
    edited 2012-12-07 19:47
    Will do, with any luck Ill get to it this weekend
Sign In or Register to comment.