Yeah, the copter is fun. What I like is that you can adjust the sensitivity from 40 - 100%. At 40% its very easy to fly, at 100% it’s harder but more fun in open area.
that’s awesome would love to see the controller that controls all those moves and the code that runs it must be one intense program.
Amazing robot!
Thanks for the comments guys!
Today we (I and two of my youngest kids) did our first outdoor test on a basketball court. It worked fine and I was able to control it very well, rolling straight, to the left and right! It’s just like driving a RC car.
Compared to the MKI the rolling method by pushing out only one section didn’t work very good. The reason was that the sections are a bit heavier on MKII, so when pushing out one section the “ball” tends to roll towards the opposite direction as I want, this method work for rather slow rolling though. But the best approach was to push out the opposite sphere (the other side of the globe) at the same time to sort of keep the ball in balance. This method proved to be more effective, it moves more like a tread, kinda…
Still some tuning to do on the code.
I gave my 8 year old son my phone to shoot a short video of MorpHex for you on the forums, so it’s a bit shaky. It’s live sound this time and unlisted. I want to make a better video when going public though.
Let me know what you think. Thanks.
Looks great! And lots of fun
Thanks Kurt, yeah it sure is fun!
Very nice, how do you implement the roling like that ? It’s a complete mode and you just give it acceleration and direction command ?
Whoa…this robot is crazy…I like it…but I’ve never seen anything like it.
Anything “Zenta” touch become “Crazy” …!!!
Thanks Eric!
The rolling part is a mode that only work when it’s folded like a ball (of course). The code is rather complex, but here is a part of it (pretty messy I guess… ):
[code]; MorpHex
; Select Sphere Level
ActivateSphereLevel:
Branch iNumButton, [NotUsed, SL1, SL2, SL3,NotUsed,NotUsed,NotUsed,NotUsed,NotUsed,Btn9SL0]
SL1:
GOSUB CheckFeetandBodyPositions
IF ((SphereLevel = 0) and (AllowLevelShift = 1)) Then ;Must also find a way to move from SphereLevel 2 to 1,
SphereLevel = 1
bHighLegLift = 0 ;Use low leglift height
bSplitSphere = 1 ;Force splitmode if activate “D” FK->IK in spheremode
sound cSpeakerPin, [50\4000,10\2000]
gosub XBeeOutputString@_SphereLevel1]
GaitType = 1 ; Use Tripod gait
GOSUB GaitSelect
FOR LegIndex = 0 to 5
LegSphereXZPos(LegIndex) = cHexInitXZ ;Set them all to the start value cHexInitXZ when entering 1. SphereLevel
NEXT
;By pre-setting these we avoid the gait to be started when entering 1. SphereLevel :
SphereXZPos = cHexInitXZ
CycleCounter = StepsInGait
ENDIF
IF (SphereLevel = 2) THEN ;Do I need to do more?
SphereLevel = 1
sound cSpeakerPin, [50\4000]
gosub XBeeOutputString@_SphereLevel1]
ENDIF
return
SL2:
;At this moment MorpHex are in true sphere shape!
IF (((SphereLevel = 1) and (AllowLevelShift = 2)) OR (SphereLevel = 3))Then
SphereLevel = 2
sound cSpeakerPin, [50\4000]
gosub XBeeOutputString@_SphereLevel2]
ENDIF
return
SL3:
IF (SphereLevel = 2) Then
SphereLevel = 3
sound cSpeakerPin, [50\4000]
gosub XBeeOutputString@_SphereLevel3]
ENDIF
return
Btn9SL0:; Button 9 = SphereLevel 0
IF (SphereLevel = 1) and (bPacket(PKT_RPOT) = 0) Then ;RPOT must be 0 before entering back to normal hexapod mode again
SphereLevel = 0
sound cSpeakerPin, [50\4000]
gosub XBeeOutputString@_HexapodMode]
ENDIF
CycleCounter = StepsInGait
NotUsed:
return
;--------------------------------------------------------------------------------
;MorpHex
SphereLevelControl:
IF NOT((bPacket(PKT_RPOT) > (Old_RPOT_Packet + 1)) OR (bPacket(PKT_RPOT) < (Old_RPOT_Packet - 1))) THEN ; Sort of traveldeadzone for RPOT
IF NOT ( (bPacket(PKT_RPOT) = 0) OR (bPacket(PKT_RPOT) = 255) ) THEN
bPacket(PKT_RPOT) = Old_RPOT_Packet
ENDIF
ENDIF
Branch SphereLevel, [Level0, Level1, Level2, Level3]
;*** SphereLevel 0 ***
Level0:
;This code make it possible to do bodymorphing combined with leglifting (no actual walking), just like we do for SphereLevel 1
IF (GearAngle1 =(400+ ((bPacket(PKT_RPOT)1400)/255))) THEN
IF (CycleCounter<= (StepsInGait-1)) THEN ;Make sure that one tripod gait (8 steps) are completed
TravelRequest = 1
CycleCounter = CycleCounter + 1
ELSE
TravelRequest = 0 ;Stop gait when one complete gait cycle is done
ENDIF
ELSE
TravelRequest = 1
CycleCounter = 0 ;Reset counter
ENDIF
;GearAngle1 = (400+ ((bPacket(PKT_RPOT)1400)/255))
GOSUB SmoothControl (400+ ((bPacket(PKT_RPOT)1400)/255)), GearAngle1, 2], GearAngle1 ;Using right pot for direct control of the inner body servo, 40 - 180 deg travel.
GOSUB SphereControl(bPacket(PKT_RJOYLR) - 128),(bPacket(PKT_RJOYUD) - 128),1]; Control the upper sphere section in stick-mode
;debug
;hserout 1, “Gear:”, dec GearAngle1, " TravelRequest:", dec TravelRequest," CycleCounter:", dec CycleCounter ,13]
return
; SphereLevel 1 ***
Level1:
IF (CycleCounter = (StepsInGait + 1)) THEN ; Do one more cycle before performing the "Snap In"
SphereXZPos = (-cMinBR+cMinTarsRadius) ; This is the sphere position
FOR LegIndex = 0 to 5
LegSphereXZPos(LegIndex) = SphereXZPos ;Set them all to the Sphere position, they "Snap In" instead of lifting the legs
NEXT
ENDIF
IF (CycleCounter = StepsInGait) and (SphereXZPos = (-cMinBR+cMinTarsRadius+cSnapInDistance)) THEN; Ready for a "Snap In" to the Sphere position
;MorpHex are now ready for entering SphereLevel 2, enable some code here?
AllowLevelShift = 2
TravelRequest = 0 ;Stop gait
CycleCounter = CycleCounter + 1
ENDIF
IF NOT ((AllowLevelShift = 2) and (bPacket(PKT_RPOT) = 255)) THEN; Don't update SphereXZPos when these conditions are in place
IF (SphereXZPos = (-(((bPacket(PKT_RPOT))*(cHexInitXZ + cMinBR-cMinTarsRadius-cSnapInDistance))/255) +cHexInitXZ)) THEN
IF (CycleCounter<= (StepsInGait-1)) THEN ;Make sure that one tripod gait (8 steps) are completed
TravelRequest = 1
CycleCounter = CycleCounter + 1
ELSE
TravelRequest = 0 ;Stop gait when one complete gait cycle is done
ENDIF
ELSE
TravelRequest = 1
CycleCounter = 0 ;Reset counter
ENDIF
SphereXZPos = -(((bPacket(PKT_RPOT))*(cHexInitXZ + cMinBR-cMinTarsRadius-cSnapInDistance))/255) +cHexInitXZ ;This makes the SphereXZPos to go from +cHexInitXZ to -cMinBR(+cMinTarsRadius+cSnapInDistance) controlled by RPOT
AllowLevelShift = 0
ENDIF
GOSUB SphereControl(bPacket(PKT_RJOYLR) - 128),(bPacket(PKT_RJOYUD) - 128),1]; Control the upper sphere section in stick-mode
;debug
;hserout 1, "SphereXZPos:", sdec SphereXZPos, " TravelRequest:", dec TravelRequest," CycleCounter:", dec CycleCounter ,13]
;hserout 1, "RPOT:", dec bPacket(PKT_RPOT), " Old:", dec Old_RPOT_Packet, 13]
return
;*** SphereLevel 2 ***
Level2:
;Read IMU
;** Disable Body Rotation and Leg FK!
;ActiveUSSangle1 = IMUstuff ;This value must be set after reading the IMU when entering the level 2
IF (ABS(bPacket(PKT_LJOYUD) - 128)> cTravelDeadZone) THEN
ActiveUSSangle1 = ActiveUSSangle1+((bPacket(PKT_LJOYUD) - 128)188/100) ;Should work like a speed function (old note: 127236/100= 300 deg, max value about 230 -> 240 = 188/100
ENDIF
IF ActiveUSSangle1 > 1800 THEN ;Making sure the value is in the range -1800 to 1800
ActiveUSSangle1 = -1800 + (ActiveUSSangle1-1800); e.g: if ActiveUSSangle1 = 1880 then it should be -1720
ELSEIF ActiveUSSangle1 < -1800
ActiveUSSangle1 = 1800 + (ActiveUSSangle1+1800) ;e.g: if ActiveUSSangle1 = -1880 then it should be 1720
ENDIF
;Test:
GOSUB SphereControl[ABS(bPacket(PKT_RJOYUD) - 128)5,ActiveUSSangle1,0]; Control the upper sphere section in roll-mode
return
;** SphereLevel 3 ***
;Test, Caterpillar mode. Very similar to level 2
Level3:
;Read IMU
;** Disable Body Rotation and Leg FK!
;ActiveUSSangle1 = IMUstuff ;This value must be set after reading the IMU when entering the level 2
IF (ABS(bPacket(PKT_LJOYUD) - 128)> cTravelDeadZone) THEN
ActiveUSSangle1 = ActiveUSSangle1+((bPacket(PKT_LJOYUD) - 128)*188/100) ;Speed function. LjoyUD define the rotation amount and direction of rotation
ENDIF
IF ActiveUSSangle1 > 1800 THEN ;Making sure the value is in the range -1800 to 1800
ActiveUSSangle1 = -1800 + (ActiveUSSangle1-1800); e.g: if ActiveUSSangle1 = 1880 then it should be -1720
ELSEIF ActiveUSSangle1 < -1800
ActiveUSSangle1 = 1800 + (ActiveUSSangle1+1800) ;e.g: if ActiveUSSangle1 = -1880 then it should be 1720
ENDIF
;Test:
GOSUB SphereControl[ABS(bPacket(PKT_RJOYUD) - 128)*5,ActiveUSSangle1,0]; Control the upper sphere section in roll-mode
return
;-------------------------------------------------------------------------------
;MorpHex
;[CheckFeetandBodyPositions]
;Check that the feet and body are in correct position before entering SphereMode
CheckFeetandBodyPositions:
IF (AllowLevelShift = 2) THEN
return ;Or do something else here when entering from 2. to 1. Level
ENDIF
IF (BodyRadius = 80) THEN
For LegIndex = 0 to 5
IF LegXZconst(LegIndex) = (BodyRadius + cHexInitXZ) THEN ;Check if each leg are in the correct position
AllowLevelShift = 1
ELSE
AllowLevelShift = 0
return ;Return as soon as one of the feet are out of position
ENDIF
Next
ELSE
AllowLevelShift = 0
ENDIF
return
;------------------------------------------------------------------------------
;MorpHex
;Use right joystick for individual/rotational control of the upper and lower sphere sections
; |90
; 180 |
;-----X----- 0
;-180 |
; |-90
;
;Angle range per leg:
;LF: 90 -> 150
;LM: 150 -> 180 and -180 -> -150
;LR: -150 -> -90
;RF: 30 -> 90
;RM: -30 -> 0 and 0 -> 30
;RR: -90 -> -30
SphereControl[Xstick,Ystick, USC_StickMode]:
FOR LegIndex = 0 to 5
UpperSphereFactor(LegIndex) = 0 ;reset all at first
TempSF(LegIndex) = 0
NEXT
IF USC_StickMode = 1 THEN
GOSUB GetAtan2 [Xstick,Ystick]
StickAngle1 = ((ATan4*180) / 3141)
;Compensate StickAngle with the GearAngle:
StickAngle1 = StickAngle1 - (GearAngle1-400)
IF StickAngle1<-1800 THEN
StickAngle1 = StickAngle1+3600
ENDIF
;XYHyp2 contain the amount of joystick direction, must be limited to max 640
XYHyp2 = (XYhyp2/20)max 640 ;(max XYHyp2/20 is 905), why not divide with 28?
;The stick angle calced from X and Y from the joystick must be converted to a factor that decide how much the upper sphere must be lifted
;when the joystick position is centered in relative to one sphere, the sphere is lifted to max.
;The stickangle must be converted to an absolute value from 0 to 600
;The UpperSphereFactor must be multiplied with XYhyp2 then divided by SphereDivFactor (at later stage),
; is a max value of 640(max XYHyp2)x600(max UpperSphereFactor) = (384000) divided by the available range limited by the right slider
ELSE ; Now the Xstick and Ystick contain XYHyp2 and StickAngle value directly, used in SphereMode 2 for rolling (hopefully)
XYHyp2 = Xstick max 640; XYHyp2 now contain the amount of sphere movement
StickAngle1 = Ystick ; valid range is -1800 to 1800 (ActiveUSSangle1)
ENDIF
IF (bPacket(PKT_RSLIDER)<230) THEN ; No point of doing this if the sphere sections are to high
SphereDivFactor = 384000/(cUpperSphereMax1 -(cUpperSphereMin1 + bPacket(PKT_RSLIDER)*5));Factor = 314 when slider is 0
IF SphereLevel = 3 THEN
SphereBias = 250 ; try this bias
ELSE
SphereBias = 0 ;No bias
ENDIF
GOSUB CalcSphereFactor ;calcl UpperSphereFactors
IF ExtendedPeak = 1 THEN
for LegIndex = 0 to 5
IF UpperSphereFactor(LegIndex)>300 THEN
UpperSphereFactor(LegIndex) = (300+((UpperSphereFactor(LegIndex)-300)*2))MAX 600
ENDIF
next
ENDIF
IF USC_StickMode = 0 THEN ;We are in roll-mode! The lower sphere section(legs) are now controlled by the UpperSphereFactor
;swXYhypUS
IF ((SphereLevel = 2) OR (SphereLevel = 3)) AND (bPacket(PKT_RJOYLR)< 128)THEN
swXYhypUS = XYhyp2*100/(100-((bPacket(PKT_RJOYLR) - 128)*4)) ;Try XYHyp2 = 400 to be center = 640*100/160, (bPacket(PKT_LJOYLR) - 128)*10/32 mean range of +/- 40
ELSE
swXYhypUS = XYhyp2
ENDIF
for LegIndex = 0 to 5 ;
;Also need to adjust the Ypos code here:
;NOTE: LegPosY(LegIndex) = cInitPosY(LegIndex) is the default value
;IF ((UpperSphereFactor(LegIndex)*XYhyp2/SphereDivFactor)/8) < 45 THEN ;max is 152, here limited to 45
;PosYRollComp = ((UpperSphereFactor(LegIndex)*XYhyp2/SphereDivFactor)/8)
;ELSEIF ((UpperSphereFactor(LegIndex)*XYhyp2/SphereDivFactor)/8) > 80
;PosYRollComp = 45 - (((UpperSphereFactor(LegIndex)*XYhyp2/SphereDivFactor)/8)-80)
;ELSE
;PosYRollComp = 45
;ENDIF
;NOTE: SphereXZPos = (-cMinBR+cMinTarsRadius) ; This is the sphere position
;LegSphereXZPos(LegIndex) = (-cMinBR+cMinTarsRadius) + (UpperSphereFactor(LegIndex)*XYhyp2/SphereDivFactor)/8 ;div/10 converting 0-1220 range to 0-122
;*********************
;Define lower leg section in ROLL mode:
LegSphereXZPos(LegIndex) = (UpperSphereFactor(LegIndex)*swXYhypUS/SphereDivFactor);*2/3
;*********************
;LegPosY(LegIndex) = cInitPosY(LegIndex) + PosYRollComp/2
;test debug:
;hserout 1, " FA_", dec LegIndex,":", sdec USfemFKpwm(LegIndex)," TA:", sdec UStibFKpwm(LegIndex), " USC:", sdec UpperSphereControl1(LegIndex)]
;hserout 1, " LPY_", dec LegIndex,":", sdec LegPosY(LegIndex)," LXZ:", sdec LegSphereXZPos(LegIndex), " c:", sdec PosYRollComp]
next
;hserout 1, " BPY:", dec BodyPosY, 13]
ENDIF
ENDIF;IF (bPacket(PKT_RSLIDER)<230), else the spherefactor is 0
;Safety, anticrash function. Make sure that the upper sphere doesn’t get in conflict when expanding body:
IF GearAngle1>400 and GearAngle1<=720 THEN
IF bPacket(PKT_RSLIDER)< 50 THEN
bPacket(PKT_RSLIDER)= 50; Adjust the Rslider for avoiding conflict with upper sphere sections
ENDIF
ELSEIF GearAngle1>720 and GearAngle1<=1700
IF bPacket(PKT_RSLIDER)< 96 THEN
bPacket(PKT_RSLIDER)= 96
ENDIF
ELSEIF GearAngle1>1700
IF bPacket(PKT_RSLIDER)< 82 THEN
bPacket(PKT_RSLIDER)= 82; The upper sphere can be lowered a little when body is fully expanded
ENDIF
ENDIF
;**Set the actual angle value for each Sphere section:
;Try to adjust the amount of upper sphere range by using RJOYLR:
IF ((SphereLevel = 2) OR (SphereLevel = 3)) THEN
IF (bPacket(PKT_RJOYLR)> 128) THEN
XYhyp2 = XYhyp2100/(100+((bPacket(PKT_RJOYLR) - 128)4)) ;Try XYHyp2 = 400 to be center = 640100/160, (bPacket(PKT_LJOYLR) - 128)10/32 mean range of +/- 40
nUSFemurComp = (((bPacket(PKT_RJOYLR) - 128)/16) min 1)max 4 ;???
ELSE
nUSFemurComp = 1; Default no compensation
;XYhyp2 = XYhyp2100/160
ENDIF
ENDIF
for LegIndex = 0 to 5
;Using the Right slider for direct control of all sphere parts
;MKII The upper sphere control is defined only here, might need to change this! max 1275
;*********************
GOSUB SmoothControl (cUpperSphereMin1 + bPacket(PKT_RSLIDER)5+(UpperSphereFactor(LegIndex)XYhyp2/SphereDivFactor)),UpperSphereControl1(LegIndex),4], UpperSphereControl1(LegIndex)
;********************
next
;debug:
;hserout 1, “Angle1:”, sdec CSFeffectAngle1(0), " Angle2: “, sdec CSFeffectAngle1(1),” StickAngle:" , sdec StickAngle1,13]
;hserout 1, “CSFLoopCnt:”, dec CSFLoopCnt," Angle:" , sdec StickAngle1," RF:",dec UpperSphereFactor(cRF)," RM:",dec UpperSphereFactor(cRM)," RR:",dec UpperSphereFactor(cRR),|
;" LF:",dec UpperSphereFactor(cLF)," LM:",dec UpperSphereFactor(cLM)," LR:",dec UpperSphereFactor(cLR), " SDF:", dec SphereDivFactor, 13]
;hserout 1, “aRF:”, sdec UpperSphereControl1(cRF)," aRM:", sdec UpperSphereControl1(cRM)," aRR:", sdec UpperSphereControl1(cRR),|
;" aLF:", sdec UpperSphereControl1(cLF)," aLM:", sdec UpperSphereControl1(cLM)," aLR:", sdec UpperSphereControl1(cLR),13]
return
;--------------------------------------------------------------------
;[CalcSphereFactor]
;Calc the amount each sphere section pushes out, determined by the StickAngle.
;This output a UpperSphereFactor for each section with values ranged 0 to 600.
;The SphereBias affect the neighbour sphere
;--------------------------------------------------------------------
CalcSphereFactor:
IF CSFLoopCnt = 1 THEN
IF StickAngle1 >= 0 THEN ;Dual rotation effect:
CSFeffectAngle1(0) = StickAngle1 -1800
ELSE
CSFeffectAngle1(0) = StickAngle1 +1800
ENDIF
ENDIF
IF CSFLoopCnt = 2 THEN ;Tripod rotation effect
CSFeffectAngle1(0) = StickAngle1 + 1200
CSFeffectAngle1(1) = StickAngle1 - 1200
;Adjust to correct angle range (-1800 to 1800):
For Index = 0 to 1
IF CSFeffectAngle1(Index)>1800 THEN
CSFeffectAngle1(Index) = CSFeffectAngle1(Index) - 3600
ELSEIF CSFeffectAngle1(Index)<-1800
CSFeffectAngle1(Index) = CSFeffectAngle1(Index) + 3600
ENDIF
next
ENDIF
For Index = 0 to CSFLoopCnt ; Reuse the LegIndex variable
IF Index > 0 THEN
StickAngle1 = CSFeffectAngle1(Index-1); Set new angle value for the current loop
ENDIF
IF (StickAngle1>=0 AND StickAngle1<300) THEN ;RM upper range:
TempSF(cRM) = 600 - StickAngle1; Value 300-600, meaning StickAngle = 0 => Factor = 600
TempSF(cRF) = (StickAngle1 + SphereBias) max 300 ;When moving towards RF Angle -> 300, the value goes from 0 to 300
ELSEIF(StickAngle1<0 AND StickAngle1>-300) ;RM lower range:
TempSF(cRM) = 600 +StickAngle1; Value 300-600
TempSF(cRR) = (-StickAngle1 + SphereBias) max 300 ;When moving towards LR Angle -> -300, value goes from 0 to 300
ELSEIF (StickAngle1>=300 AND StickAngle1<900) ;RF range:
TempSF(cRF) = 600 - ABS(600-StickAngle1); Value 300-600
TempSF(cLF) = ((StickAngle1 - 600 + SphereBias) min 0) max 300 ;When moving towards LF -> 900 the value goes from 0 to 300
TempSF(cRM) = ((600 - StickAngle1 + SphereBias) min 0) max 300 ;When moving towards RM -> 300 the value goes from 0 to 300
ELSEIF (StickAngle1>-900 AND StickAngle1<=-300) ;RR range:
TempSF(cRR) = 600 - ABS(600+StickAngle1); Value 300-600
TempSF(cRM) = ((StickAngle1 + 600 + SphereBias) min 0) max 300 ;When moving towards RM Angle -> -300, value goes from 0 to 300
TempSF(cLR) = ((-StickAngle1 - 600 + SphereBias) min 0) max 300;When moving towards LR Angle -> -900, the value goes from 0 to 300
ELSEIF (StickAngle1<=1800 AND StickAngle1>1500) ;LM upper range:
TempSF(cLM) = 600 - (1800-StickAngle1); Value 300-600
TempSF(cLF) = (1800 - StickAngle1 + SphereBias) max 300 ;When moving towards LF Angle -> 1500, the value goes from 0 to 300
ELSEIF (StickAngle1>=-1800 AND StickAngle1<-1500) ;LM lower range:
TempSF(cLM) = 600 - (1800+StickAngle1); Value 300-600
TempSF(cLR) = (1800 + StickAngle1 + SphereBias) max 300 ;When moving towards LR Angle -> -1500, value goes from 0 to 300
ELSEIF (StickAngle1>=-1500 AND StickAngle1<=-900) ;LR range:
TempSF(cLR) = 600 - ABS(1200+StickAngle1); Value 300-600
TempSF(cRR) = ((StickAngle1 + 1200 + SphereBias) min 0) max 300 ;When moving towards RR Angle -> -900, value goes from 0 to 300
TempSF(cLM) = ((-StickAngle1 - 1200 + SphereBias) min 0) max 300 ;When moving towards LM Angle -> -1500, the value goes from 0 to 300
ELSEIF (StickAngle1>=900 AND StickAngle1<=1500) ;LF range:
TempSF(cLF) = 600 - ABS(1200-StickAngle1); Value 300-600
TempSF(cLM) = ((StickAngle1 - 1200 + SphereBias) min 0) max 300 ;When moving towards LM -> 1500 the value goes from 0 to 300
TempSF(cRF) = ((1200 - StickAngle1 + SphereBias) min 0) max 300 ;When moving towards RF -> 900 the value goes from 0 to 300
ENDIF
For LegIndex = 0 to 5 ;Use the largest value on each SphereFactor:
IF UpperSphereFactor(LegIndex)<TempSF(LegIndex) THEN
UpperSphereFactor(LegIndex) = TempSF(LegIndex)
ENDIF
next
next
return[/code]
And yes, it’s like driving an RC-car.
Like you said “rather complex” code…
How does the servo handle the weight for long term use ?
Have you change the gears yet ?
The servos with titanium gears seem to hold up fine so far. I’ve not replaced any gears yet. “Only” replaced the inner body servo from 5645 to 5990TG. You can read more about that on my blog (I’m a bit tired of double/tripple posting… )
The servos do get very hot after a 15-20 minutes session, especially with much walking.
I understand, sorry…
Oh don’t be! My point was just that I’m sorry for not always posting the same information on both Lynxmotion.net and the Trossen forum. So I found it useful to post more details on my blog.
I just added your blog to my RSS feed…
I just added your blog to my RSS feed…
Great
Hi,
I’ve been trying to add a serial IMU sensor to MorpHex. The code is pretty simple and its working fine on an ARC-32 with this code:
[code];*** ARC-32 + Razor 9DOF IMU AHRS code test program ***
;This program simply grab the serial stream from the IMU using Hardware serial, hserin.
sRoll var sword
sPitch var sword
sethserial1 h57600
pause 100
hserout 1,"*** ARC-32 + Razor 9DOF IMU AHRS code test program ***",13]
pause 10
main:
hserin 1,TimeOut,200000,[WAIT("!ANG:"), sdec sRoll, sDec sPitch]
pause 1
hserout 1,“Roll:”, sdec sRoll, " Pitch:", sdec sPitch,13]
pause 50 ;pause simulate phoenix code in process
goto main
TimeOut:
hserout 1,“Timeout”,13]
pause 5
goto main[/code]
As you can see I’m using hserin 1 (TX from IMU to pin2 on JP5/UART, BAP RXD), simply because UART 2 is occupied with XBee communication. I’m using SSC-32, so I’m not controlling the servos using HSERVO.
In my MorpHex code I’m using the same code within the controlinput sub. Using this line of code:
hserin 1,IMUTimeOut,200000,[WAIT("!ANG:"), sdec swXimu, sDec swYimu]
But when connecting the IMU to the ARC-32 on MorpHex the servos go crazy and I can hear from the vibrating sound on the speaker (when it beeps) that the pins probably get corrupted somehow. The code seem to run more or less ok, since I’m able to monitor the IMU data through UART1. It’s funny, even when the IMU is turned off, the bug occur when connecting the TXD from IMU to BAP RXD.
I’ve also tried software serial. Of course that does not affect the SSC-32 communication, and the robot and code work fine. But for some reason the IMU readings get corrupted. So I can’t trust software serial either. Using this line of code to read IMU:
serin RxIMUpin,i57600,[WAIT("!ANG:"), sdec swXimu, sdec swYimu]
I’ve no idea where this come from. The big ARC-32 mystery LOL.
I’m hoping someone like Kurt have an idea whats causing this?
Hi Kåre,
My first guess is yes, the hardware interrupts to read on the serial data from the IMU is corrupting the data being sent out from the Arc32 to the SSC-32. (Was one reason my Phoenix just had the Arc32 and not the SSC-32 with it… ) But not anymore .
If you remember with the Bap28/Arc32 Phoenix code when we are using the XBee, I have code to disable the XBee sending data, while we output the SSC-32 data. Not sure how to do the same thing with this device. I don’t see any IO pins or the like that allow you to tell the IMU that you don’t wish to receive any data. The external connector shows DTR and CTS, but looking at the schematic, I don’t see it actually connecting up to anything. Not sure what the best way would be to keep it from corrupting the SSC-32 data.
As for Software Serial, it will only receive characters while it is actually in the serin…
One approach may be to update the firmware on the IMU, to have some form of simple control. Like maybe use one of the SPI pins that are part of the ISP connector and use it to control when data is sent…
Sorry I am not seeing anything easy or obvious.
Is this the IMU you are using? sparkfun.com/products/10736
Thanks for your fast reply Kurt!
Ah, I see. I’m using this IMU from sparkfun, an older version of the one you posted. Looking at the schematics, like you suggested the only option would be MOSI (PB3) or MISO (PB4). I hope they can be access in the code, maybe just check PB4 before sending serial?
If not I could simply use an external OR gate or a NAND gate (use a 2. NAND for inverting the output of the first NAND). I think I’ve some old TTL and CMOS chips somewhere… I’m currently using a level converter, but I’m not sure if its needed since it worked fine without while running the test code on another ARC-32. I started using the level converter when I noticed the bug started when RXD-BAP went low without sending any data from the IMU, and to make sure the bug didn’t occur due to 5v vs 3,3v issue.
Thanks!
I’ve done searches on the web to find out if I can use the MISO on the IMU SPI (atmega 328 ). Hopefully I can use it as an ordinary digital input. But I’m wondering what pin number the MISO is referred to in the code. I found this pinout docs, so I assume the MISO(PB4) is pin 12 in the code then?
Hopefully I’ll get some time this evening to try it.