Forum Posts

Tom Swann
Jul 21, 2020
In Hardware
In earlier posts ( here and here), I discussed needing some custom parts. Specifically, these were custom standoffs between the Nybble frame and the NyBoard and also between the NyBoard and a Pi. At that time, I made the parts from wooden dowel material. This got the job done and fit the Nybble organic (wood) vibe. However, when I recently got access to a 3D printer, I thought I would revisit the topic from a more general customization perspective. In Thingiverse, one can find items that can be customized, including various kinds of standoffs. The customization makes use of OpenSCAD, a script (.scad file) based 3D CAD modelling application. Members of Thingiverse have created and posted .scad files which are parametric descriptions of the models for the customizable items. When you change parameter values (width, height, etc.) OpenSCAD will render models and create an .stl file for printing items customized to your specifications. MakerBot (the owner of Thingiverse) host a web app called "Customizer". This web app allows you to change and visualize the effects of different parameter values in a .scad file and to submit a job to the server that will do the actual rendering and conversion to a .stl file. The visualization is ok though a bit slow but the server jobs can take a very long time to complete (server seems to have chronic problems). In this post, we will use OpenSCAD directly rather than deal with such server delays. Credit: The brief information in this post are based on a web page from "Dr. Lex" at https://www.dr-lex.be/3d-printing/customizer.html. Please view that location for many more details. Steps: Download and install OpenSCAD on your computer (https://www.openscad.org/downloads.html ) Locate customizable items in Thingiverse by searching with keywords like "customizer", "customizable", etc. We will use the "Customizable Standoff Generator" (see this link). On that Thingiverse page, click on the link "Thing Files" to get a list of files available. Download the ".scad" file. Note that without a .scad file, the item cannot be customized. Start OpenSCAD. If the "Welcome to OpenSCAD" splash screen appears (initial default), click the Open button and navigate to open the .scad file you downloaded. Otherwise, use the menu sequence File > Open to do the same thing. In the Customizer panel of OpenSCAD, expand the different parameter sections by clicking the "triangles": In OpenSCAD, for each parameter, enter the desired value. Here we will build an array of 4 identical round standoffs that are 11 mm high x 8 mm wide with a 3 mm through-hole. Use the menu sequence Design > Render then File > Export... > Export as STL... to save the rendered model as an .stl file. Slice and then 3D print from this .sfl file. The accuracy and precision of the printed items depend on your printer but here is what I got on an Ender 3 Pro FDM 3D printer for a single print job of the 4 "identical" standoffs targeting the dimensions of 11 mm high x 8 mm wide. Length: 11.37, 11.38, 11.43, 11.42 Width: 7.90, 7.88, 7.89, 7.91 So here, the accuracy could be better but the precision is good. If you find this post interesting and/or useful, please click the like button. If you have other ideas on how to create helpful additional parts for Nybble, please post them.
Using OpenSCAD to 3D print customizable parts - a very brief tutorial content media
1
2
466
Tom Swann
Jul 10, 2020
In Software
I have found it useful and interesting to create tools that help me better understand and think about the OpenCat framework. I'd like to use this post to share those tools. Below is the first one - I will add other tools here in future updates. Excel transform() visualizer The transform() function (in OpenCat.h) is used to transition from a set of current joint angles to a set of target joint angles. The function calculates the number of intermediate steps (small angle changes) to use in the transition, based on the parameter speedRatio. The function then does a transformation using cosines. The Excel transform() visualizer plots this transformation and demonstrates how use of cosines gives an initial acceleration from a current angle, then a pseudo-linear range of angles and finally a deceleration to the target angle. Here is an plot of step vs. dutyAngle for current angle = 0 deg, target angle = +45 deg and speedRatio = 1 (45 steps). This poses the question of what other transform functions we might try that give different effects (faster movement, more cat-like movement, more robotic movement,something else?), especially as we string transforms together in behaviors. What are your thoughts and what would you like to try?
OpenCat Tools content media
1
3
153
Tom Swann
Jul 07, 2020
In Software
I have been spending a lot of time with the 'm' (move) token and the 'j' (joint list) token and decided that I wanted more information for the latter. In the current default Nybble.ino, the 'j' token switch case looks like this: case 'j': { //show the list of current joint angles printList((int8_t*)currentAng); break; } So, this token accesses the printList() function which has the following code: template <typename T> void printList(T * arr, byte len = DOF) { String temp = ""; for (byte i = 0; i < len; i++) { temp += String(arr[i]); temp += '\t'; //PT((T)(arr[i])); //PT('\t'); } PTL(temp); } and it produces a simple bare list of joint angles from joint index 0 to 15 (pose kbalance is shown): The printList() function is also used by the 'c', 'm', 'u' and 'b' tokens and I didn't want to change their behavior so I made the following new function: template <typename T> void printJointListTS(T * arr, byte len = DOF) { PTL(); //TS Joint Name Header grid PTF("hPan hTilt tPan NA "); PTF("rFL rFR rHR rHL "); PTF("sFL sFR sHR sHL "); PTLF("kFL kFR kHR kHL"); //TS Min Max Joint Angle grid PTF(" -58 +112 -25 +32 -59 +110 xxxx xxxx "); PTF("xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx "); PTF(" -71 +100 -95 +75 -100 +67 -64 +106 "); PTLF(" -73 +62 -59 +112 -70 +70 -110 +59"); //TS Create matching jointIndex and jointAngle data grid for (byte jointIdx = 0; jointIdx < len; jointIdx++) { //TS For info on sprintf() function, see See https://www.programiz.com/cpp-programming/library-function/cstdio/sprintf char jointIdxChars[3]; //TS Expected range is 0 to 15 so need 2 chars plus 1 char for \0 terminating char sprintf(jointIdxChars, "% 3d", jointIdx); //TS Use space padding of width 3. char jointAngleChars[4]; //TS Expected range is 000 to 180 so need 3 chars plus 1 char for \0 terminating char sprintf(jointAngleChars, "%+ 4d", arr[jointIdx]); //TS Use sign with space padding of width 4. PT(jointIdxChars); PT(": "); PT(jointAngleChars); PT(" "); //TS Char count: 3 + 2 + 3 + 2 = 11 to match test grid } PTL(); } When this new function is substituted into the 'j' token switch case, we get this more informative list (again for pose kbalance): The first line is a list of joint names, the second line is a list of min and max joint angle values and the third line has colon delimited joint indexes and current joint values with everything lining up nicely due to use of the sprintf() function. Note that the first and second lines are hard coded. In particular, you have to determine the min and max joint angles for your Nybble manually via 'm' token usage. This adds a new function with significant hard coding of the first 2 lines so what is the memory price? Memory Change: +2008 bytes (ca. +6%) program memory; +16 bytes SRAM. Kind of expensive so you might want to add compiler directives (#define, #ifdef) to switch between the original code and this code. Of course, if you turn off the unnecessary code in IRremote.h, and pick up ca. 10% program memory (see here), you might be able to leave this code on all the time. Let me know if you find this useful.
More Informative Joint Angle List Code content media
2
0
55
Tom Swann
Jul 06, 2020
In Clinic
Problem: There is erratic behavior from the following sequence using the serial monitor: 1. Use the skill token, 'k' to give a gait skill command, say walk, " kwk". o Nybble executes the gait skill command properly. 2. Use a non-skill token, say 'd'. o Nybble processes the token properly. 3. Use the skill token, 'k' to give the SAME gait skill command as above (again, "kwk"). o Nybble now executes the SAME gait skill command incorrectly giving erratic behavior. Video: Nybble in the new training safety harness (link). Kitten goes from 'd' to kbalance then follows above sequence [kwk, d, kwk] via the serial monitor to show the erratic behavior. Final token of 'd' used to calm Nybble down! Note: The standard unmodified Nybble.ino was used. Diagnosis: In the loop() function of Nybble.ino, there is a "motion block" section of code that is responsible for looping a gait skill to provide continuous motion. All token 'k' gait skill commands use this "motion block" but other token's do not. In that motion block is this code: int dutyIdx = timer * WALKING_DOF + jointIdx - firstMotionJoint; calibratedPWM(jointIdx, motion.dutyAngles[dutyIdx] ... This code uses the "timer" variable to step through the frames in the gait skill ("timer" = 0 to motion.period) and access the correct angles for each joint index. All is well until the above problem sequence is used. The first step in the problem sequence starts the gait skill and the second step interrupts the gait skill, leaving "timer" at a some value (last used) from 0 to motion.period. The third step in the sequence attempts to do the same gait skill again but the code does not either reset "timer" back to zero (restart) or synchronize the traverse of the gait skill frames with the last value of "timer" (resume). The result is erratic behavior as the frame angles are matched to the wrong joint indices because "timer" is now out of sync. Solution: One easy solution is a quick code modification to do an explicit restart (reset "timer" to zero). Line 643 of Nybble.ino has the following code which controls access to resetting "timer": if (strcmp(newCmd, "") && strcmp(newCmd, lastCmd) ) { During step 3 of the problem sequence, the first part of this line, "strcmp(newCmd, "")" evaluates to true because newCmd has the gait skill name (e.g. "wk") so that's good. However, the second part, "strcmp(newCmd, lastCmd)" evaluates to false since newCmd and lastCmd have the same gait skill name (e.g. "wk") and timer can't be reset. So, changing line 643 to the following allows the timer to be reset: if (strcmp(newCmd, "") ) { Result is a happy kitten! 😸
Specific case of an erratic behavior problem with a diagnosis and solution. content media
0
4
56
Tom Swann
Jul 06, 2020
In Showcase
As I was making code changes, I decided it was hard to see what was going on with Nybble thrashing around on the floor or threatening to leap off the table. So, Nybble now has training safety harness. Here a motion sequence at lower battery voltage [460 (begin) to 449 (end)]: kbalance, kwk, kbk, kbalance, d Here the same motion sequence at high (freshly charged) battery voltage [555 (begin) to 548 (end)]: kbalance, kwk, kbk, kbalance, d Higher battery does give a faster motion but there is not as much difference as I expected. BTW, these are more or less "normal" conditions where the gyros are enabled and SKIP is disabled in these tests. The skills are unmodified. Video is at 720p (60 fps).
Nybble Gets A Training Safety Harness content media
2
4
190
Tom Swann
May 20, 2020
In Hardware
Can anyone recommend ways to mount a Pi Zero W on the Nyboard v2 and also how to make the connections between these two boards? Pictures to illustrate would be very helpful too! Thanks in advance!
0
8
535
Tom Swann
More actions