Question about a previous post

Hi, I added some things onto a previous project I had posted a while back, BH-3 Hexapod that sharette was helping me with but never received a response. The forum has changed since my original post so maybe that’s why. I was wondering if you could take a look at my last post from that thread so I won’t have to start over again. Thanks!

Hey! Welcome back! :slight_smile:

Yes, I have a strong suspicion the transition to the new community web site (including this forum) have something to do with this. After the original transition we’ve had a few issues where answers to older topics (from the previous forum) were not “watched” anymore and therefore got no notifications. It is all resolved now, but it was an issue for a bit… :expressionless:

So, my most sincere apologies to you! You were not ignored on purpose… :smiley:

As for your last post, time to have a look at it!

Had a quick look at your code (MandibleHex.ino). I notice no delay or reduction in the input… i.e.: your loop will take a few hundred cycles running at (most likely) the default clock rate of 16 MHz.
This means the loop as is will most likely run thousands of times (or more) in the time it takes you to press down then let go of the button on the gamepad.

A useful approach in such cases is to buffer input. For example:
On a first press, do the action once. Then, after a set amount of time if the button is still held repeat the action a certain amount of time per seconds (or said differently, repeat it every “x ms” or something; ex: 10 Hz > once every 100 ms). If the button is let go at any point in time cancel this action and return back to waiting for the first press.

A good example of this is a keyboard on a modern OS. If you hold a key down for a few seconds you don’t get millions of characters on the screen right away! Instead, the action happens once and after an initial delay it repeats a certain amount of times per seconds (usually configurable in your OS).

Of course, you’ll have to add some extra data structures to keep track of each button’s state and such. Maybe the PS2X lib already does this for you?

Here are some good references to help you get started:
https://www.arduino.cc/en/Tutorial/Debounce
https://electronicshobbyists.com/arduino-button-tutorial-using-arduino-digitalread-function/
https://www.instructables.com/id/Arduino-Button-Tutorial/
http://andybrown.me.uk/2010/11/22/debounced-buttons-with-auto-repeat-in-avr-c/

Though instead of trying to debounce the input your goal is to prevent ultra-fast repetition! :slight_smile:

I hope this helps!

Sincerely,

Good to be back, thanks for the response! And thanks for the useful resources as well. Glad you’re still around.

I added a small delay at the end of my code and that smoothed things out greatly. I also noticed that on one line for tilt I mistakenly had “buttonPressed” where it should have been “buttonReleased”. Pan/Tilt works great now!

Once I have time to clean things up a bit I’ll send some vids!

1 Like

:slight_smile:

Careful with adding a delay. That is only a patch, not a fix. The issue with delay (and the trouble with most Arduino examples) is that this idles the CPU, therefore doing nothing else in that time. I highly recommend learning how to use millis instead.

Good luck with the project!

Ah I see, I cheated! I will study on this some more. Had a question: when I reviewed the code from my rover project https://community.robotshop.com/forum/uploads/default/original/3X/a/3/a3ec848db0267ad924df3abd38605c136828fe9a.ino I didn’t see any instance of this kind of structure. Did I miss it or was handled in a different way?

Indeed! :wink:

I highly recommend to. It is useful knowledge and (should) not (be) that big of a gap to fill from where you are currently anyway.

Well, a quick search tells me the keyword delay appears 7 times: 3 in setup (inconsequential), 4 in the main loop. Of those last 4, one is in debug code (line 315; 100 ms). If debug is active it will execute every run loop. Next one is at line 523 & 543; 10 ms. These two only seems to be executed if certain FSR-related stuff is enabled. Last one is at line 721; 30 ms. This one is executed at every run of the loop.

It should also be noted that this loop has a lot more stuff to do than the other one you were testing which depending on execution time may be adding hundreds of ms in delay already! Maybe add a print every loop end of millis() and see how much time each loop takes in this one compared to the other code you posted in this topic.

Sincerely,

Ok thanks, I see. A couple more questions please. Does adding debug code slow the loop down as well? In other words could adding it be beneficial to my code? I was in a hurry when I wrote the code for my current project and didn’t add any debug code because the ps2 was working without any issues. Could you give some thoughts on debugging code that might be helpful? I feel I may not be grasping the full use/purpose of adding debug code.

Thanks!

Well, adding any code takes processing time. That processing time is not 0. :slight_smile: So, yes, it does. Depends on what the debug code is doing, of course.
Simple (integer) counters (ex: i += 1; ) take very little time (a few CPU cycles), but stuff like division, Serial.print/println, and other complex tasks will take far more time.

Debug code is beneficial in the sense that it helps you debug your code (hopefully… :smiley: )!
The fact that it produces a delay is a side effect and is not a desired way to slow down execution of a function (or loop).

Typically, “debug code” is added to investigate an specific issue with the code you are developing. If you have no issues you would most likely not have extra code in.
One thing to keep in mind (I think even more important in embedded development) is to make sure the presence (or absence) of the debug code does not change the behavior you are trying to debug! Otherwise you may have a very difficult time identifying the issue/the cause/the solution.

Whenever you encounter a situation that does not work as expected you’ll need to find clues about why that is happening to help you determine how to correct it. Typically, you can first look at the code; sometimes simple mistakes in ordering things can break algorithms in spectacular ways (or really subtle, mundane ones! :stuck_out_tongue: ).

You may also want to examine values of various variables at different points in your code to help determine where the situation goes from what was expected to not. Serial.print/println/write can be helpful here. You may also just store results in an array and output those at the end, too. Very helpful for cases where printing at every loop would delay specific code too much (code where timing is key).

I hope this helps.

P.-S.: Search around the net for various articles on debugging, such as this one. They vary greatly in details (and quality), but they’ll all help give you a glimpse into someone else’s experience with debugging code.

Just another question please: in regards to “buffering input” does the same concepts apply to the joysticks of the ps2? Or is this more in regard to buttons? I would like to slow down the speed of the mandible servos and I wonder if buffering may help achieve this goal. Or would it be more of a adjustment using a “speed” variable. I hope to do some experimenting this weekend. Thanks!

Hey!

Yes! You should have a function that transforms your input (joystick position) into the output (mandible motion/speed). And this input should be read over a certain range of time but applied slower (i.e.: buffered) to prevent really fast motion/instant motion to min/max position.
That being said, unlike buttons being pushed, joystick positions are different because they are not “pushed or not pushed” and instead have a position (typically viewed as a delta from the center).

Therefore, something simple like “the further my joystick axis is placed from the center, the faster I move the mandibles in that direction” would be a simple way to describe the desired behavior.

Maybe something along the lines of:

x = (centerPos - joystick.getAxis()); // Or some other method that gives a ±delta from center
y += f(x);

Where x is the delta from center, y is the mandible position and f(x) is your function that transforms one coordinate system (joystick delta) into another (motion delta for motor/mandible).
Your f(x) could be a simple function, like f(x) = (x * k + c);, where k represents your linear constant and c is your offset.

Side note: the AVR libc, AFAIK, only supports float (not double), so keep that in mind if you use very small numbers that require high precision. You can read more here (Arduino related) and here (float/double related).

Sincerely,

In effect, the example above is basically converting a position (x) into a speed (f(x)) and apply to y repeatedly every loop.

The magic comes from choosing the right combination of f(x) and how often to apply it (from every loop to far, far less). Of course, the best would be to apply it every loop for maximum responsiveness while having a f(x) that converts that delta into a small enough speed amount so it does not cause instant motion to min/max.

Since as mentioned above the ATmega based Arduinos cannot do double (only float), that limits how small numbers can be due with precision.

Also, another note: for example, if you apply your speed value every 4 loop runs, you are effectively /4 your speed value that is applied to the mandible position… :wink:

Good luck with your experimentation!

P.-S.: You may also want to search online about adding a moving average, which could smooth out the motions of the mandible.