Firmware

Firmware and code for M-O. Check out our Git Repo to view the full source code!

Overall Firmware Architecture

We created an Arduino library, Mo_Lib, to hold all of our code. This library contained two main classes: Robot and Controller. These hold all of the variables and functions for the robot and controller respectively. The robot class contains functions for receiving radio messages as well as functions for controlling both the body and head of the robot. The controller class contains functions for reading the input from the joystick and buttons then sending this info via radio to the robot.

Movement

Driving

The code for driving based on joystick input is split between a few functions. The first,.readStick(), gets the X and Y values of the driving joystick. These are then sent via radio from the controller to the robot, where they are passed into a function calcMotorSpeeds() that converts the joystick value into a speed for each of the motors to drive at, which can be positive or negative based on the direction. Finally, setMotorSpeeds() tells the four motors to drive at the calculated speeds.

Head

The code for moving the head is split between a few functions. It reads data from the right joystick in the controller and sends it via the same method that the drivebase motion is sent.

However, instead of affecting the speed of the head - which is a relatively top heavy object - the X input to the joystick's direction is taken and the head is moved in that direction for the duration that the joystick sends input in that direction. This is done by calling the step_left() and step_right() functions depending on the joystick reading.

Arm

The movement of the arm functions in a similar way to that of the head; however, the input data from the controller is different. As opposed to a joystick, the arm’s movement is controlled by two buttons - one to move it down and one to move it up. Data from all six buttons on the robot are sent as a bitstring and the first two of these represent whether the “arm up” and the “arm down” buttons are being pressed.

Based on the direction, the arm movement is then completed by calling the same functions as the head to step the arm, with it moving up/down as opposed to left/right.

Face

LED Matrix

The LED matrix is used to represent M-O's face and displays his various different expressions.

When initially exploring what to use for M-O's face panel, we looked at various types of Neopixel and LED screens where we found that either the price, quality, or size were not suitable to what we wanted. Some of the criteria we were looking for included the following:

  • Colored LEDs (at least yellow)
  • Quality similar to that of M-O in the movie -
  • Large enough to distinctly see the eyes make different expressions
  • One single element
  • Can be wired to Arduino with enough remaining pins for radio chip data

Based on this criteria, we settled on a 16x32 pixel LED Matrix with the RGB Matrix Shield from Adafruit.

Matrix 1

We started by coding the following functions to display basic expressions on the RGB Matrix:

  • blank_eyes() - clears the screen by setting all the pixels to off
  • default_eyes() - M-O's default open eyes
  • big_eyes() - M-O's eyes when widened
  • closed_eyes() - M-O blinking
  • horiz_line() - M-O horizontal line glitch
  • angry_eyes() - Angled eyes that appear mad

All of the expressions were based off clips from the movie itself:

Since we wanted to make two animations for M-O - one happy and one angry - we wrote two functions happy_animation() and angry_animation() that cycle through some of the expressions at varying rates.

Finally, we connected the radio chip to the matrix shield and used inputs from the controller to call the various expressions and animations.