Next large robot



  • Yesterday was spent doing mechanical calibrations on the legs. I ended up doing it several times as later adjustments affected earlier changes. So I had to stop and figure out the right procedure for making adjustments.
    The only mechanical adjustments available are on the femur and tibia linear drive motors. The output shaft can be manually turned to shorten or lengthened and that affects the leg positioning. Ignoring a couple of hours of changes that I made initially that made the problem worse, I finally figured out the right way. Calibration requires adjusting the tibia first against a known angle and follow that with the femur.
    I adjusted the tibia by using an electronic protractor to get the angle the leg supports were at (this would be normally vertical) and adjust the tibia until it read the same angle (so they were basically in line with each other). Adjusting the femur was done by shortening all the femur drive shafts to their minimum position initially. Next was taking an interior angle off the parallelogram on each leg when all the slack is taken out of the leg. Once I knew the largest angle, I adjusted all the other femurs to get the same angle.
    I found that leg #6 was still not not quite right. I determined the leg was 1/4” shorter than the others. Since all the parts are interchangeable this should not be happening. It turns out the leg bottom impact assembly was actuated all the time, hence the 1/4” difference. I disassembled the part but didn’t find any thing obvious so far. It was getting late so today I will figure that problem out too!
    Also on the agenda is checking the leg angle limits for tibia and femur against the programmed values and then verify the electronic calibration values. If any leg is still different than the others then a programmable ‘fudge factor’ will be used to make sure it gets into alignment with the other legs.

  • I couldn’t find anything mechanically different on Leg #6 but the centering o-ring was pushing the leg up. It’s supposed to be a tight fit to keep the leg from moving too much so I took about 0.005 off the groove the o-ring rides in using the lathe. That seemed to help a lot and the leg settled into the expected position.
    The next step was extending all the legs to their maximum position. This lifted the robot body off the test stand and put all the weight on the legs. I found that legs #1, 3, and 5 were carrying all the weight and 2, 4, and 6 were not fully extended. 2 of the legs were touching the ground but the leg wasn’t compressing the bottom impact spring. Leg #6 was 1/8” above the ground. I measured the angles on the legs and found there was a 5º difference in the legs. I suspected that the encoder maximum setting was stopping the legs from going as far as they needed to. I tried increasing the encoder maximum and found that improved the position but the linear motor reached its movement limit. This meant extending the motor output shaft to permit a longer movement. So this became a combination of mechanical and encoder changes until I could get the motor to extend the leg to where the bottom impact spring fully compressed but didn’t cause the legs on either side to lift up. This took a lot of trial and error to slowly find the right combination. Then repeat the process for the other 2 legs. That took up most of the time in the shop today!
    The end result is all six legs are firmly planted on the ground equally!
  • I felt that I was far enough along that I could remove the test stand. Boy was I wrong! There's a reason I named this video Hexapod Fails!

    It took a while to recover, no damage to the robot but some of the motors were getting too hot to touch. I also managed to get some rope burns out of this, time to get a better rope, very hard to hold onto poly rope without it slipping.
    I have a list of issues to correct, first off I'm writing a routine to validate the IK angles are not out of range (which is what happened when the coxa motors suddenly went to one extreme. After watching the video I figured out that I was only applying the IK routine once at the beginning of the move, it should be applied more frequently as the leg is moving to get everything in synch. That is why the leg tips were sliding on the floor.
    Anyway I learned a few new things today, mostly what not to do! Back to the drawing board again. This video was taken using my GoPro, the wide angle lens is almost too much, I liked my old Cannon G12 better for video. I may have to get another one like that again. The Olympus is nice but the focus tends to jump around which makes it difficult to get a good video, I have ended up deleting most of the files I created using it.

  • Bob, that's great progress. We have been waiting a long time for the birth. :) Got to crawl before you walk.

    Glad you could get some videos.

  • I take back where I said no damage from stalling the motors. I was checking wiring to fix a power wiring error (I can turn the computer power on without having the key switch on) when I found the the battery disconnect was melted. This plug is rated for 30 amps and none of the motor fuses blew. I need to replace this and put a fuse directly on the battery power line. I didn’t find any other damage to the wires, the wires don’t show any damage. I’ll be taking the cover panels off so I can inspect all the wiring more closely and look for heat damage to the insulation. The wires on the melted plug seem to be OK, maybe the plug itself wasn’t fully engaged and it developed a high resistance across it?
  • Another issue found, Leg #1 tibia would not respond to movement commands. After validating the HB-25 was not blown, wires from the leg controller to the motor controller were good and wires to the motor were good I removed the motor for closer inspection. When I applied 12v to the motor there was no movement. Opening up the motor I found one wire to the commutator was not connected, the way it failed it appeared that the solder joint was not good and the extra heat generated was enough to make it separate. I added some flux and re-soldered it down successfully. Leg was re-installed and tested out fine.
    I was able to go over all the main power wiring and did not find any other issues other than a melted power disconnect. Based on the amount of melting involved with the connector I would have expected that I would have seen some wire damage also. But absent wire damage I believe now that the connector was not fully seated and created a high resistance connection resulting in excessive heat only at that place. I had to use an Exacto knife to cut the melted plug apart but it appears to be usable until I can replace it.
    I tested out some new code for the leg controller to prevent the leg from moving if an invalid movement command was received. Previously if a command was outside of the movement limits the leg would move to either the minimum or maximum position. It made sense at the time but not anymore.
    Started researching on eliminating floating point math in the master computer. Found some great discussions on the P1 site on CORDIC and generation of Sine, Cosine, and ATAN. I need to study the examples more but this may be the answer for speeding the angle calculations up and still getting a faster response to the motors.
    Another item on the immediate To-Do list is getting the current leg positions when the robot is started up so the master computer knows what position values to assign. Each leg already calculates each motor position angle during its startup routine, now I need to get that position info back to the master.
  • watching you video reminds me of my Irish Wulfhound Lilly.

    She like to lay down on the hard wood floor, but has a hard time getting up again from there, with feets sliding in all directions at the same time. It is quite comical to watch.

    But I see the same problem with your robot, feets sliding on your slippery floor.

    Maybe you should put some rubber on each foot, like used on canes and such?


  • [quote="msrobots;c-1463552"
    Maybe you should put some rubber on each foot, like used on canes and such?

    There are furniture rubber feet on the end of each leg. The legs weren’t supposed to slip, IK is supposed to keep that from happening. Unfortunately I didn’t use IK correctly in the code. I was making movements based on checking IK once and then going a a large distance without compensating for the angle changes. I should have only moved the height in short distances and called the IK routine so the tibia would have adjusted to keep the leg tip in the same position.
    Although the initial trial without the test stand didn’t go as expected, I learned some good lessons to be applied before I let the robot run free again!
    I’ve already coded some fixes, one of the most important was to make sure the legs don’t go to their extreme positions if the input is incorrect (that was I figured out happened when the coxa motors moved the legs from 90º to 30º instead). Time for some more test stand work!
  • Land animals have ankle joints and feet for a reason. The current feet on your robot will limit it to hard surfaces and small angular movements of the legs. A ball joint foot would probably make a big difference in the range of motion it can handle.
  • AT-AT style footing? Just so long as no one ties a rope around the legs! :smile:
  • I did look on-line for some different style rubber feet, was seeing if I could find something that was more round-ish with a 1” diameter hole. That shape could give more support to the leg tips. I’ve also seen where the leg tip is on a ball joint that will automatically adjust to the ground contour, that could be good for outdoors walking. Unfortunately I didn’t see anything by searching for furniture protectors. Need to come up with other search terms instead.
    Didn’t get too much accomplished, the living room remodeling project has gone into overdrive and I spent a lot of time getting walls fixed, repainted, carpet removed and new floating floor installed. Tomorrow will be replacing the baseboard and curtains so we can move everything back into the room. Then we will be moving everything in the dining room into the living room and starting all over again!
    I did manage to sneak away for a bit each day to run power to the master computer from the on-board battery. Looking for a small 100amp shunt to add so I can monitor overall current draws. I think the fuses I’m using are too big and I need to go with smaller sizes on the motor circuits.
    I spent some time reviewing hexapod code used on other processors and how using integer math for sine, cosine, ATAN. Got some good ideas, they created some DAT lookup tables. Although the sine table is hardcoded, based on earlier threads a table lookup is faster. Right now I have lots of available memory, this might take care of that! Floating point math is slow, I did a quick test moving all 6 legs in 0.25” increments using IK, there is a noticeable delay and i could actually see when each leg got an update to move. I need to speed that up, I know it is possible as I have seen other prop based hexapods that don’t show that much delay. There are some tricks that can be used also since some movements are just the same just opposite directions, could calculate once and then use the values for more than one leg at a time.
  • Looking for a small 100amp shunt to add so I can monitor overall current draws.

    If you have a 100A fuse already you can solder small wires directly to the fuse and use it as the shunt resistor. You can then use an INA219 or similar board/chip to monitor both current and voltage. Of course you will have to come up with a calibration factor for the current.
  • I put some additional support between the robot and the test stand so I can get it off its feet for now while I test software changes. I was moving all the legs up so the body would rest on the test stand but leg #2 wasn’t cooperating.
    Finally I just removed the leg and found that the tibia motor was not responding even when I applied 12vdc directly to the motor. Disassembling the motor I found that one bushing was not touching the commutator. Closer inspection showed heat damage to the plastic mount for the bushing. Luckily I was able to make repairs to the bushing holder so that the bushing slides on the commutator again so the motor is working. This is an indication of a heat buildup due to the motor being unable to move the leg. I’m adding code to check for stalled motors by checking the encoder value through each loop and if it doesn’t change then disable the motor and throw an error message.
    Once I get these code changes done and tested then I’m going to video some movements using the existing floating bit IK routines. Then I’m going to change everything over to integer math and use sin, cosine and tangent lookup tables in the DAT to speed things up. I’ll video the same movements so I can directly compare the speed differences and post those here. I still need to setup the leg to master feedback loop, its still a open loop system now.
  • The stalled motor routine is up and running, power to the motor cuts out after 10 passes through the PID loop with no encoder change. Hopefully that will eliminate locked rotor over-current draws and the high temperatures involved with that!

    I got the feedback loop running between the master and leg. I have a dedicated cog that cycles through each leg sending a query for a response ($,legnumber,CR). The selected leg then outputs status on each motor plus a miscellaneous status ($,femur,tibia,coxa,misc). I coded the misc. status as showing whether all motors have completed movements. Each status output is then reflected in the RGB lights for each motor. If a light is green then the motor completed its movement, different colors are used during actual movement depending on the movement direction. I need to solder the network cable together, so far I just tested this using one leg. I’ll get that setup next and test each leg is sending status data out correctly.

    A potential problem is that the master uses the 4 port FullDuplexSerial object and I use the RX command to get the response from the selected leg. The problem is that the RX command waits for an input so the loop stops until a response is received (I’m not cycling through all the legs because of this). According to the object, the RxTime (.rxtime(data,millisecond) should move on after the ms pause but it didn’t work that way in my code, it still hung up there. I’m worried that if a leg can’t respond for some reason then feedback from the other legs will be lost and could be bad depending on what actions are being taken at the time.

    Still planning on videoing a comparason of floating and integer math speeds, just want to get the feedback setup first. With the existing open loop system I have to determine when a motor has completed movement and add pauses in the code to allow it to finish a movement before sending the next command. With feedback this won’t be a problem and should get better control over leg movements
  • I finally soldered together a network wiring harness using some shielded 3 conductor wire and several male test jumpers that were cut in half. One wire is for the master to leg with position data, one way communications only. The other 2 wires are a transmitt and receive line between the master and legs. The communications protocol is the same as I described in the previous posting.
    Of course after taking out the temporary feedback wires to leg#3 and replacing the previous network cable I made (I cut the wires too short and they kept pulling out of the female sockets on the RoboPi boards) and putting in the new wire things didn’t work exactly right.
    The leg position communications from the master to the legs still works properly, I can send data to any leg from the master and the right leg responds. However the master to prop communications for the feedback loop didn’t want to work any longer. After performing several tests with no response, I finally removed the 2 feedback wires from all the legs except Leg#3. And it worked exactly as it did before. So when I re-added the wires to Leg#4 it stopped working again. If I removed Leg#3 feedback wires, then Leg#4 starts working. So the code seems to be OK and it’s some type of problem with the network itself, not sure what to do at this point as I’m fresh out of ideas. I verified that the new cable isn’t shorted or open on any pins. I tried a search on the Prop1 board but searches there are difficult to find anything with the forum software so I posted the question over there. Hopefully someone has an idea for me to try out. It could be a coding issue also but the fact that it works with a single leg confuses the issue. I will post the code as soon as I get my PC setup again, we are remodeling the office and the computers are in the living room. My programming computer in the basement is not connected to the internet so I have to copy the files to a flash drive and use my upstairs PC to read the flash drive. I use an iPad for most of my postings but it doesn’t have a way to upload the flash drive so I’m stuck for now.

  • Hi @DiverBob,

    nice progress. I saw those RGBs in the video cool feedback.

    Can you post the version of 4-port serial you are using, I can take a look at the rxtime function and how to use it, as far as I remember it did work.

    Since you are retired now you need to do more exercise so going upstairs and downstairs is good for your health...


  • msrobots wrote: »
    Can you post the version of 4-port serial you are using, I can take a look at the rxtime function and how to use it, as far as I remember it did work.
    I’m using FullDuplexSerial4Port object. I will post the code as soon as I get to computer that I can plug in a flash drive!
  • I forgot my wife has a SurfacePro so I am able to upload the leg and master controller files. The communications occurs in the MasterComs pub on the leg code. On the Master the code is in GetColor pub.
  • Thats a start I will look, but I am still missing your 4-port serial object, there are different versions out, which one you use?

  • Ok, first thoughts.

    You start 4-port serial in COG 0 but run your MasterComs in another COG. This might be a issue. Not sure if 4 port serial can handle this.

    And if you have non blocking IO that would not be needed. Both belong into the same main loop.

    I try to explain.

    Both getcmd routines wait until they have received a complete command. Even if they do not have any byte in their buffer. But they should not do that just return some -1 value or so to say 'nothing there'.

    And the main routine should just execute the routines if getcmd's return ;I have a command'. else just run the main loop.

    I play a bit with your source and post some code instead description, but still would like to have your 4-port serial spin to check against.

    stay tuned,

  • msrobotsmsrobots Posts: 3,191
    edited 2019-02-15 - 08:40:19
    All right the first step

    I change the main loop of the leg code to include MasterComs and expect my Getcmds to check if there is any data or return with -1

    So if no data is send on any channel the loop does not wait but loop.
      'start of main loop
       'serial feedback output to master - shared with all controllers. No output until master requests, then send everything
       'initial output is motor angle data, FemurAngle, TibiaAngle, CoxaAngle  
        bytefill(@combuffer,0,64)                                                   'add 11/18/18, copy from main loop
        'command string from master
    '    io.str(0,string("combuffer:"))
        if getcmd1("$", @combuffer, 62)>-1                                          'cmd from master for feedback (port2, pin8)
    '      io.str(0,@combuffer)
          if extractfield1(1, @combuffer, ",") == leg                               'if true, cmd is for this leg          
            if FemurColor == Red OR TibiaColor == Red OR CoxaColor == Red
              MiscColor := Red
              MiscColor := Green
          'transmit string format ($,1,2,3,4), "$" start; 4 values
          'output feedback; example - when FemurDone flag = true then FemurColor = Green  
           buildstring(FemurColor, TibiaColor, CoxaColor, MiscColor)
    '      io.str(0,@outbuf)
        'movement main loop
        if Manualentry == 0                                 'added 5/16/15, allow manual control of leg
          'command string from master
          RESULT := getcmd("$", @buffer, 20)                'using RESULT as flag -1 nothing ther >-1 has command
        else                                                'added 5/16/15
          ' start manual entry via terminal - enter using $,leg,command,angle - angle entry 62.5 = 625
          RESULT := 0                                       'we have a command
        if RESULT >-1                                       'do we have a command? 
          'set angle commands for leg
          if extractfield(1,@buffer, ",") == leg
          'check for other leg commands
          'calibration values for PID loop - "$,7,leg,motor,Kp,Ki"
          if extractfield(1,@buffer,",") == 7
            if extractfield(2,@buffer,",") == leg
              if Manualentry == 1
                io.str(0,String(13, "PID calibration values: "))
              case extractfield(3,@buffer,",")
                1:  Kpf := extractfield(4,@buffer,",")
                    Kif := extractfield(5,@buffer,",")
                    if Manualentry == 1
                      io.str(0,String(13,"Femur kp: "))
                      io.str(0,String(9,"ki: "))
                2:  Kpt := extractfield(4,@buffer,",")
                    Kit := extractfield(5,@buffer,",")
                    if Manualentry == 1
                      io.str(0,String(13,"Tibia kp: "))
                      io.str(0,String(9,"ki: "))
                3:  Kpc := extractfield(4,@buffer,",")
                    Kic := extractfield(5,@buffer,",")
                    if Manualentry == 1
                      io.str(0,String(13,"Coxa kp: "))
                      io.str(0,String(9,"ki: "))
            '4- set speed - $,8,Leg,motor,speed                                         
          if extractfield(1, @buffer, ",") == 8
            if extractfield(2,@buffer,",") == leg
              if Manualentry == 1
                io.str(0,String(13, "Set Motor Speed: "))
              case extractfield(3, @buffer, ",")
                1:  fSpeed := extractfield(4,@buffer,",")
                2:  tSpeed := extractfield(4,@buffer,",")
                3:  cSpeed := extractfield(4,@buffer,",")

    now none of both should block each other.

    now to getcmd and getcmd1, I show getcmd1
    pub getcmd1(hdr, pstr, len) | idx, k, char                                       'routine designed by Jon McPhalen
    ' get command from serial stream                                                 'copy for use by another cog
    ' hdr is required header character
    ' pstr is pointer to string space for command
    ' len is maximum length of input (buffer len-2)
    ' RETURNS -1 if no data/timeout
        char : = io.rxtime(2,500)
        if char == -1
          RESULT := -1                                                              'timeout/nothing there
        byte[pstr][0] := (k := char)                                                ' get char from stream
        if (k == hdr)                                                               ' if header
      if RESULT == 0    
        idx := 1                                                                    ' set starting index
        repeat while (idx < len)
          char : = io.rxtime(2,500)
          if char == -1
            RESULT := -1                                                              'timeout/nothing there
          byte[pstr][idx] := (k := char)                                        ' get char from stream
          if (k == 8)                                                               ' if backspace
            idx := --idx #> 1                                                       ' backup
          elseif ((k == 0) OR (k == 13))                                            ' if 0 or CR, quit
            ++idx                                                                   ' advance pointer
        byte[pstr][idx] := 0                                                        ' terminate string

    this now uses rxtime and when it timeouts (after500ms) it returns. It is not really perfect yet because it blocks for 500ms when no data is there but should never block and recover from any transmission error.

    You have to do the same for getcmd and you can remove the cogstart of MasteComs and PUB MasterComs from the leg controller.
    And have one cog moer free in the leg controller.


  • Thanks for looking over the code! I will try out your suggestions and see what results I get. It might be a day or two, we are remodeling and took out the carpet from the dining room last night so my wife has me putting in the new floor and baseboards today! I hope to sneak out at some point and get into the workshop for some fun time!
    The .rxtime was a test just to see how it worked, normally I have .rx() in there. I think I didn’t change it before I copied the code. Running MasterComs in another cog works when I just have a single leg controller connected, its only when I put 2 of them in there that it stops. The reason I used a seperate cog in the first place is that the GetCmd routine stops at the .rx() and wouldn’t proceed and I wanted the leg feedback independent of the main loop. I missed that the .rx() returns -1 and I could use that to test for a command coming in without totally stopping the main loop.
    If I can put everything in the main loop then not only do I not need the MasterComs cog but getcmd1 can go away also and just use getcmd. GetCmd1 was just for the seperate cog to prevent 2 cogs from calling the same code at the same time. I’ll try it all out and report back.
  • yeah, that is basically what the code I wrote is doing,

    have fun with it, I just want to nudge you in a better direction.


  • I’m in the process of trying out the suggestions to the code first. I’m running version 1.01 of FullDuplexSerial4PortPlus from Tracy Allen.

    I modified my main loop and the getcmd and getcmd1 code to match the examples. I found that using .rxtime but it never appears to timeout and gets stuck at the command. I changed to .rxcheck and the code passes through to the next code section. I verified this by just printing to the terminal before and after the commmand to see if the second item printed to the terminal.
    After manually running the leg code I changed it to run from the master and setup the master getcmd routine with the same code. First test shows it working with the feedback data showing up on the RBG LEDs (that turns out to be a great troubleshooting aid by watching the color changes to know what the leg is doing while the PST is connected to the master). I changed the feedback loop to look at both leg 3 and 4, both sets of LEDs are now displaying. Checking for -1 results for no communications data is allowing the loop to continue even without the leg responding. Next I’ll wire the network cable back in another leg to the network and see how that works.

    The wife is back so time to get back to work on installing the baseboard in the dining room. Although I got the floor installed faster than I expected, my back was severely protesting afterwards so I took a break to the couch for the rest of the night!
  • I updated all the leg controllers to the updated program version and on the master controller I can cycle through all the leg controllers without it stalling, waiting for a response. Initially I only had leg#3 connected using the new network wires, one wire for transmit from the master to the leg and the other is for the master to receive from the legs. The master polls each leg controller in turn and asks for a response, obviously only leg #3 will respond since it was the only one connected. However, I was getting no response for leg#3 but I was getting a response after Leg#5 was polled. I made sure I didn't load the wrong code to either leg when I realized that leg#3 was moving but leg#5 LEDs were displaying the movement. I figured that after polling the leg there needed to be a bit of a delay before going on to the next leg so I added a 25msec delay on the loop and sure enough Leg#3 response came in correctly now. This comes from trying to use the rxtime code to allow a short wait for a character but for some reason it isn't performing as expected, it never times out. I put in rxcheck instead and get an immediate response. I need to figure what I'm doing wrong as the rxtime is a better way to handle this vs a generic wait.
    After this I hooked up the rx and tx lines to both leg#3 and leg#4. Unfortunately now neither leg responded. I pulled the rx/tx wires from leg#3 and now leg#4 worked. It seems as if the leg transmit pin is not in a high impedance state when it isn't being used so the pin drags down the signal from the polled leg controller so nothing gets through. I tried pulling the line high with a 600K resistor and that didn't make a difference either. The transmission from the master to the legs appears to be working OK, I use the same method for sending the leg movement commands from the master to the legs with no issues so far. The problem seems to be only with the legs transmitting back to the master via the common wire.
    I included the master and leg software so if someone sees something out of place let me know!
  • Frustration is kicking in so I’m about ready to change the communications software design so the operating master port2 will also receive data from the slaves instead of having a seperate port just for that. I separated out the 2 functions since the master has to send out all the leg movement commands to the robot legs and then wait until each leg completes its movement. The RoboPi boards were to broadcast the actual status of the leg movement throughout the move and get that info back to the master via a seperate cog. Once all legs had successfully completed a movement then the next move command would be sent. I’m thinking of ways to combine these items into a single loop on the master as an alternative.
    Another option would be to add another 4port object to the master and dedicate one port for each slave to continuously transmit movement data to the master. That would be easiest to accomplish in software since there would be no data contention issues to deal with and I can store the input from the legs in variables the master software can read at any time.

    I have gotten a lot of help in troubleshooting this issue from the folks over on the Prop1 forum where we know what the issue is (too much loading on the master to leg transmission wire). It seems to be an issue with the RoboPi board or leg software (signal voltage from the master with no RoboPi boards connected is 3.3vpp per the o-scope which drops to 2.08vpp when the first board is connected and then down to around 1.0-1.16vpp with the second board plugged in - signal attenuated too much at this point and the prop doesn’t see the signal). I would really like to get to the bottom of this problem but it’s occupied several days of testing and frustration with no real solution in-sight. It may be time to try a different solution soon (leaning towards option#2 above as the easiest to implement...).

  • msrobotsmsrobots Posts: 3,191
    edited 2019-02-22 - 01:31:18
    wrong thread
  • I have gone over the schematic for the RoboPi board and if the attached block diagram is how the boards are connected there is no hardware cause for the problems. If the connections are different could you please post an accurate diagram.
  • kwinn wrote: »
    I have gone over the schematic for the RoboPi board and if the attached block diagram is how the boards are connected there is no hardware cause for the problems. If the connections are different could you please post an accurate diagram.
    That’s one of the first things I checked was to verify the schematic layout. It has connection points before and after a protection fuse, I was connecting to the connection that goes directly to the prop pin.
    I created a new version of the software and started coding a star setup for communications.
  • kwinnkwinn Posts: 8,565
    edited 2019-02-22 - 15:52:19
    Odd that it doesn't work. I had all 5 of my P1 boards communicating with each other over a single wire (plus common ground of course). Only difference between what you are trying to do and my setup was that I used a different pin. I may just connect my boards up using pins 30-31 and try that code again.

    BTW, forgot to post the diagram last night, so here it is.
Sign In or Register to comment.