Monthly Archives: November 2020

Basketball Shot Make/Miss Recorder

Posted 27 November 2020

After my recent right shoulder surgery, I have been looking for ways to get back into BBall shooting practice. However, the combination of Covid-19 lockdowns and the oncoming winter weather has drastically reduced my options for shooting practice. Not to be dissuaded from BBall practice, I figured out a way of moving my practice area from my driveway outside the garage inside the garage. As it turns out, our earth-sheltered house boasts an attached earth-sheltered two-car garage with a 12′ interior ceiling and no vertical support beams (I insisted on this in the design, and paid the extra cost, knowing from prior experience that interior support columns in a two-car garage was a bad thing.

Still not quite perfect, as even a 12′ ceiling isn’t quite enough room for a 10′ high BBall rim and enough headroom for practical shooting practice. So, I decided to mount my new practice rim at 9′ vs 10′, leaving 3′ of headroom. Obviously this isn’t ideal, but I figured a lot of practice on a 9′ rim was much better than no practice on a 10′ rim ;-).

As I started to shoot in my new practice gym, I realized I also now needed a way to record hits and misses so I could keep a running ‘made shots’ percentage. My short-term memory degradation due to being an old fart has made it almost impossible to do this in my head, and besides, what could be better than being able to combine my love of BBall, my love of programming, and my love for hardware/software projects? That’s at least a trifecta if not a quadfecta (and that is actually a word!). So, I programmed up a Windows program in C# to display ‘Hits’, ‘Attempts’, and ‘Hit Percentage’, and used an Arduino microcontroller to interface to two push-buttons – one for a hit, and the other for a miss. The arduino talks to the Windows program via a serial port over the USB cable, and the Windows program displays everything in a readily visible way. My idea was to use foot switches for the input so it would be easy to provided the needed hit/miss inputs without having to break out of a shooting rhythm. So, I jumped up on Thingiverse and found a neat, rugged footswitch by ‘vandenmar’. I needed two switches, so I modified vandenmar’s design by adding an additional cable routing trench out to the other side of the switch (so the switch cable can be routed in from the left or right-hand side of the switch).

My very own indoor basketball court (with a few minor restrictions…)
Nice, rugged footswitch design by vandenmar on Thingiverse
The 12 mm switch used here is available from Adafruit

Here’s a photo of the Arduino switch contoller

After getting all the pieces together, this is how it looks in my garage. The red footswitch is for ‘makes’ and the blue one is for ‘misses’.

red/blue footswitches, with cable to UNO and laptop in the background

This setup worked pretty well, but it still wasn’t quite ready for prime time. The UNO & breadboard were, well, breadboards, and not very mechanically robust. I was afraid I would spend more time repairing the breadboard than I would actually shooting, so I decided I needed to move from a breadboard to a more finished project. In addition, the Windows program I was using to display stats needed some work, so both sides (Windows and Arduino) needed some TLC.

I happened to have a Sparkfun Pro Micro module laying around in my parts bin, so I decided I would change out the UNO for the much smaller Pro Micro. With only two pushbutton switches and a Red/Green LED, the Pro Micro has plenty of I/O for the project. Here’s the Pro Micro version of the hardware layout.

So then I opened up my trusty Open SCAD ’rounded box with lid’ script and printed up a translucent enclosure, shown below

Sparkfun Pro Micro translucent enclosure. Photo above shows the ‘Make’ green LED illuminated

Next I updated the Windows program to show Makes, Misses, Percentage makes, and number of shots made in a row, along with the longest run of made shots for this session, as shown below

And here is the ‘final’ setup in my garage:

The two footswitches are shown at bottom left, with the Pro Micro enclosure hanging down from the laptop.

Here’s the schematic for the Sparkfun Pro Micro setup

And here is a short video showing the system in action.

At 0:43 into the above video you can see the green ‘Make’ LED illuminate in the background when I pressed the red ‘Make’ footswitch, and at 1:25 you can see me pressing the blue ‘Miss’ footswitch.

Stay tuned!

Frank

Solving the Teensy VL53L0X Array Controller Reset Problem

Posted 16 November 2020

Back in May of this year, I converted Wall-E2, my autonomous wall-following robot, from using HC-SR04 ultrasonic ‘ping’ sensors to VL53L0X infrared time-of-flight sensors for left & right (and now rear) distance measurement and obstacle detection, as described in this and follow-on posts. Since then, I have been successfully integrating the new sensing capability into Wall-E2’s wall-tracking and obstacle avoidance algorithms, as described in this post among others.

In recent ‘sandbox’ runs, however, I started to notice that the VL53L0X controller (a Teensy 3.5) wasn’t always providing proper distance measurements. Sometimes it would return ‘-1’ for some or all seven measurements. Eventually I figured out that the problem only occurred when I restarted the main controller via the wireless serial connection; when I restarted by cycling the power, VL53L0X measurements were always proper. After looking into this a bit, I realized that the problem occurred because the VL53L0X array controller wasn’t being restarted when the main controller was, except when everything was power cycled.

So, I needed a way to ensure that the VL53L0X array controller got restarted, even with a serial-port reset of the main controller. The Teensy 3.5 actually has a RESET function exposed on a pin pad (although internal to the PCB, not on the periphery) so I added a pin to this pad, and connected it to the wire formerly used as the ‘left ping’ control line. Then I modified the setup code to pull this line LOW for a few 10’s of milliseconds and then back HIGH again, to restart the Teensy.

To test the modification, I modified the main controller code to send a HIGH to an unused digital pin as the first instruction in setup() and set that pin back LOW again as the last instruction. Immediately after setting this pin high, the RESET signal is sent to the Teensy. The Teensy program was modified to set an unused pin HIGH at the start of it’s setup() program, and LOW at the end. By monitoring these two pins with my wondrous Hanmatek DOS1102 DSO (see below) I was able to definitively confirm that the Teensy restarts every time the main controller does – yay!

Yellow trace is main controller setup() timing, blue is Teensy VL53L0X array controller setup() timing

In the above scope photo, the horizontal scale is 1 sec/div. The yellow trace shows the main controller setup() function timing, and the blue is the Teensy VL53L0X array controller setup() function timing. The Teensy gets reset about 500 mSec after the main controller setup() function starts, and it ends about 5.5 Sec later, about 500 mSec before the main controller setup() function ends. The relative timing shown above is the same whether the main controller is restarted via a power switch cycle or a serial port re-open restart.

Stay Tuned,

Frank

Wall Tracking Trials Using Office ‘Sandbox’ Part I

Posted 12 November 2020

Back in October I added a TIMER5 timer interrupt to my autonomous wall-following robot (WAll-E2) code to manage sensor updates. Since then I have made the timer interrupt the sole timing source for all sensor and tracking updates, and upped the update rate from 5Hz to 10Hz. In addition, I’ve been making some improvements to Wall-E2’s obstacle detection/response abilities, and this post describes the results of these enhancements.

Wall-E2’s job is to autonomously track walls forever. This implies the ability not only track walls, but to deal with obstacles as they occur, and recharge its batteries at one or more provided charging stations as needed. Wall-tracking per se has been the subject of several previous posts, and is now reasonably well managed using the ‘find parallel’ technique described here. This post deals with the effort to detect and respond to obstacles as they occur. Here’s a recent run in my office ‘sandbox’

In the above telemetry printout, the first obstacle encounter occurs at 7.65 sec, corresponding to about 4 sec into the video. The obstacle is recognized at 18 cm, well inside the desired offset distance of 30 cm. I believe this occurred because the robot had just started turning back toward the near wall with a target steering value of -WALL_OFFSET_TRACK_SETPOINT_LIMIT (-0.3, the maximum toward-wall steering value) which meant that the normal forward obstacle detection limit of WALL_OFFSET_TGTDIST_CM (30cm in this case) wasn’t in force and the backup limit of MIN_FRONT_OBSTACLE_DIST_CM (20cm in this case) triggered instead. This causes the following code block to execute:

As can be seen in the above code snippet, this causes the robot to make a 90º ‘spin turn’ to the right, and then restart wall tracking.

At about 12.6 sec (about 10 sec into the movie) we see it detect the upcoming wall at about 30 cm (due to a bug in the code, the printed values are incorrect). This causes the following code block to execute:

This code executes a 90º ‘step turn’ (identical to a ‘spin turn’) to the right, and drops back into wall tracking mode.

At about 16 sec into the movie and 20 sec after program start, the robot again detects an upcoming obstacle at about 30cm, and again executes a 90º ‘step turn’ to the right to follow the new wall.

About 1.5 sec later, the robot detects one of the chair legs (I think it was the one nearest the wall in the movie) and tries to get away using another 90º ‘spin turn’, but then exhibits some abnormal behavior. When it attempts to find the parallel orientation to the new (non-existent) wall, it exits RotateToParallelOrientation(Left) with SteeringVal = -79.86, a very strange result. I believe this is because Wall-E2 detected the ‘stuck’ condition while it was attempting to complete the parallel orientation procedure, in this ‘while’ loop

So, it exited abnormally, thus the odd SteeringVal number, and then re-detected it in the main tracking loop because the front distance history array isn’t re-initialized after the first detection. This, apparently, is a ‘feature’, not a bug – who knew! ;-).

After the second ‘stuck’ condition detection, the robot attempts to disengage using the ExecuteStuckRecoveryManeuver(), which, in this case tries to back up and then execute an ‘end-around’ maneuver to get past the chair leg. It finished the backup portion of the maneuver successfully with 23cm remaining rearward, and then executed a 90º ‘spin turn’. Then it went forward 21cm using the front distance sensor (not shown in the video), and halted when I took over manual control.

All in all, this was a very successful ‘sandbox’ run. Lots of good data with clear indications of where things are working well and where things need to be modified/fixed.

  • A bug in the telemetry display code for the ‘Wall Offset Limit’ detection printout (fixed).
  • In the situation at 7.65 sec where the obstacle detection occurred at 18cm vs 30cm, the robot should recognize that it needs to back up to the wall offset target before making the spin turn (done).
  • And, of course, porting all this new stuff to the right-side tracking sections

16 November 2020 Update:

Tonight I got the first cut done at porting the TRACKNG_LEFT algorithms over to the TRACKING_RIGHT case, and made what appears to be a successful right-side sandbox run, as shown in the following short video

And here is the telemetry from the run:

Here’s an Excel plot of the Right side center distance and L/R motor speeds vs time.

Comparing the times from the video and the telemetry, it appears the video time is about 3-3.5 sec lower than the telemetry values. In the video, Wall-E2 detects the first upcoming wall at about 9 sec, and this corresponds with the telemetry at 12.358 where the wall is detected with front distance of 19cm. The reason the wall didn’t get detected earlier is the robot was currently tracking back toward the wall with a steering value of -0.3, and this causes the wall detection value to be reduced to suppress false positives.

The robot then takes 2 sec to back up to 33 cm and turn 90 deg CCW, and then it starts tracking the right-side wall again. It detects the next wall at 17.1 sec (14 sec in video) and 30 cm (the steering value at that point was 0.10, so no reduction in upcoming obstacle detection distance). Because the detection occurred at 30 cm, the robot doesn’t need to back up; it just makes another 90 deg spin turn CCW and starts tracking the right-side wall again. The last segment clearly shows that Wall-E2 is capable of tracking to and capturing the desired offset of 30 cm.

All in all, a very successful right-side sandbox run.

Stay tuned!

Frank