Skip to content

Instantly share code, notes, and snippets.

@bp2008
Last active December 2, 2023 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bp2008/dff8957bfa040be51a2c561a2b2aca51 to your computer and use it in GitHub Desktop.
Save bp2008/dff8957bfa040be51a2c561a2b2aca51 to your computer and use it in GitHub Desktop.
A guide to complete the Super Mario RPG 100 Jump challenge on Nintento Switch, using a Raspberry pi and a servo to press the A button.

Super Mario RPG has a challenge to complete 100 consecutive jumps on a single enemy. The reward is a powerful piece of armor for Mario.

2023-11-30 10 53 03 (1200)

image

It is recommended to do this in Mushroom Way (the zone directly after Mario's Pad), where you can find Spikey enemies which take no damage from jumps, allowing you to try again and again without re-entering combat with other enemies. Plus, there is a mushroom in a chest in the area northwest of the spikeys so you can refill on flower power!

I couldn't get beyond 30 jumps doing it by hand, so I found another way.

Thanks to reddit user Imaginary-Cod-8685 for the basis for this python script. https://www.reddit.com/r/MarioRPG/comments/181eu91/100_jumps_mario_rpg/

This python script was run on a Raspberry Pi 3B connected to a PCA9685 servo controller and a MG995 servo to repeatedly press the A button on a Switch Pro controller with very precise timing.

I ran sudo pip3 install adafruit-circuitpython-servokit on the pi before running the python script, in order to install the "ServoKit" library. It is also necessary to enable I2C via the Raspberry Pi config application. It is a regular GUI app on recent rasperry pi OS releases.

I have refined the script to eliminate cumulative timing error from time.sleep() calls, and in fact this code does a spin-wait instead of time.sleep between events for the most accurate and precise possible timing. To be more precise than this, I assume it would be required to drive the servo with an Arduino or something with a real-time OS.

The following script is what I used to complete the 100 jumps challenge. You will need to make modifications, at least to the nopress and pressDepth variables. nopress is the servo position in degrees for the "un-pressed" state. pressDepth is the change which should be applied to the servo position in order to cause the button to be pressed. pressDepth could be positive or negative depending on your servo positioning and which direction you need it to rotate to press the button. You want the button to be pressed fully and 100% reliably, but not pressed too hard as you could cause undue wear to the button, or excessive stress to the servo.

Important timing numbers are near the bottom in arguments to the press function.

from adafruit_servokit import ServoKit
import time

counter = 1
kit = ServoKit(channels=16)
globals()['auto'] = 'off'

time_stored = time.time()
waits = 0

def wait(s):
    global time_stored
    global waits
    global counter
    
    # You can add a time offset here if needed, but I ended up not needing to
    #if (counter == 30):
    #    time_stored = time_stored + -0.005
    
    end_time = time_stored + s
    time_stored = end_time
    while time.time() < end_time:
        waits = waits + 1
        
nopress = 130
pressDepth = -16
    
# Initialize servo at "no press" position, wait half a second
kit.servo[0].angle = nopress
wait(0.5)

def press(totalTime):
    pressTime = 0.30
    kit.servo[0].angle = nopress + pressDepth
    wait(pressTime)
    kit.servo[0].angle = nopress
    wait(totalTime - pressTime)

# Press to initiate the jumping, wait 1.52 seconds for mario to land.
press(1.52)

# Now jump in a loop with consistent timing.
# This continues until you stop the program.
try:
    while True:        
        press(0.88375)
        counter = counter + 1
finally:    
    kit.servo[0].angle = nopress
    wait(0.5)

I ran the script in the "Thonny" application which was pre-installed in Raspberry Pi OS. This application offers convenient start and stop buttons.

The hardware used is as follows (Amazon US links, not affilliate links):

  • Switch pro controller (technically optional) (wired or wireless, see what works best for you)
  • Raspberry Pi 3B (any Pi should work, however)
  • Variable DC power supply
  • PCA9685 Servo Controller
  • MG995 Servo
  • Dupont Wire for connecting the servo controller to the Pi and to the power supply.
  • Some scrap wood and screws to securely mount the servo at an appropriate height to consistently press a button on the Switch Pro controller.

I first tried this with a cheap 5 volt 3 amp power supply I had lying around, and no servo controller (servo connected directly to the pi). It was terrible. The timing was incredibly inconsistent and the servo jittered back and forth a lot. Adding the servo controller and bigger power supply completely solved that and made the servo perform very well.

I set the power supply to about 5.5 volts with a limit of 4 amps. In practice, the output only spikes up to about 1 amp while the servo is moving.

The wiring diagram for the whole setup is basically what is shown on Adafruit here (except you don't really need the breadboard): https://learn.adafruit.com/adafruit-16-channel-servo-driver-with-raspberry-pi/hooking-it-up

Diagram from Adafruit: image

Here are pictures from the final setup I used.

2023-11-30 10 55 06 (1200)

2023-11-30 10 55 38 (1200)

2023-11-30 10 55 30 (1200)

2023-11-30 10 55 27 (1200)

2023-11-30 10 55 43 (1200)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment