Ping Pong Ball Level – Code

Because this was an Arduino-based project, the team had to write a custom Arduino library including a .cpp and .h file. This library is called Balance.

Main Arduino Code (.ino):

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include "Balance.h"
#include "Adafruit_VL6180X.h"
#include <Servo.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myservo;
Adafruit_VL6180X vl = Adafruit_VL6180X();
int goal = 55;
float Kp = .08; //.9  
float Ki = .04; //.4
float Kd = .04; //.4
int servo_setpoint = 85; //1450
int error;
int sum_error;
float last_error = 0;
float D_error;
int servo;
float angle;
float last_angle = 0;
float gain = .05;
Balance balance;
unsigned long lcd_timer;
char buffer [100];
void setup() {
  Serial.begin(115200);

  // wait for serial port to open on native usb devices
  while (!Serial) {
    delay(1);
  }
  Serial.println("Adafruit VL6180x test!");
  if (! vl.begin()) {
    Serial.println("Failed to find sensor");
    while (1);
  }
  Serial.println("Sensor found!");
  Serial.println("range\tservo\terror\terror*Kp\tsum_error\tsum_error*Ki*.1");
  lcd.begin();
  lcd.backlight();
  myservo.attach(9);
  lcd_timer = millis();
}

void loop() {
  uint8_t range = vl.readRange();
  error = goal - range;
  sum_error = sum_error + error*2;
  D_error = error - last_error;
  servo = servo_setpoint - balance.PID_P(Kp, error) - balance.PID_I(Ki, sum_error) - balance.PID_D(Kd, D_error);
  last_error = error;
  if (servo > 110)servo = 110;
  if (servo < 53)servo = 50;
  myservo.write(servo);
  delay(100);
  angle = (servo_setpoint - servo); //low pass filter
  angle = angle*gain + (1-gain)*last_angle;
  last_angle = angle;
  angle = .95*angle -3.12;
  Serial.println(angle);
  //Serial.print("\t");
  //Serial.println(servo);
  //sprintf(buffer,"%d\t%d\t%d\t%.2f\n",range, servo, goal);
  //Serial.print(buffer);
  if (millis() - lcd_timer > 500) {
    sprintf(buffer, "%d", angle);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(angle);
    lcd_timer = millis();
  }
  
}

Custom Code Library Balance.cpp:

#include "Arduino.h"
#include "Balance.h"

  
Balance::Balance()
{

}

int Balance::PID_P(float Kp, int error)
{
  int PError;
  PError = error*Kp;
  return PError;
}

int Balance::PID_I(float Ki, int sum_error)
{
  int IError;
  IError = sum_error*Ki*.1;
  return IError;
}

int Balance::PID_D(float Kd, int D_error)
{
  int DError;
  DError = (D_error * Kd) / .1;
  return DError;
}

Header File for the Custom Library: Balance.h

/*
  Balance.h - Library for 412 teeter totter project.
  Created by Mitchell A. Stoltz, December 8, 2019.
  Released into the public domain.
*/
#ifndef Balance_h
#define Balance_h

#include "Arduino.h"

class Balance
{
  public:
    Balance();
    int PID_P(float Kp, int error);
    int PID_I(float Ki, int sum_error);
    int PID_D(float Kd, int D_error);
    float angle(int servo_ms, int setpoint);
  private:
};

#endif

Ping Pong Ball Level

The goal of this final project was to create something that would be unique as well as a practical use. This ping pong ball level utilizes a ping pong ball, a track, a distance sensor, a servo, and arduino uno, and an LCD display. Using these components, the distance sensor will detect where the ping pong ball is located on the track and will tell the servo to rotate the track to keep the ball in the middle. There is a set point of 0 degrees while the platform is on a level surface. While the servo is correcting the track to keep the ball in the middle, the angle of the track off of 0 degrees will be displayed on the LCD screen to show the angle of the surface this device is on.

LED Matrix – Code

Code Snippet 1
Code Snippet 2

In code snippet 1, the arrays of bytes are used to determine which LEDs in the matrix turn on. A ‘1’ denotes an activated LED. These arrays are passed to functions that parse the values and, upon reading a ‘1’ value, activate the appropriate Arduino pins to allow current to flow through the LEDs.

Code Snippet 2 shows the setup and main loop for the Arduino program. The setup function contains the pinModes for the buttons on the breadboard that activate certain light shows. The other Arduino pins that control the LED matrix board are processed within the library file. The main loop of the Arduino program reads the values of the pins connected to the buttons. The buttons are pulled low by a pulldown resistor. Upon pressing, the voltage goes high and the program cycles the loop function fast enough to catch a quick press. The value of ‘HIGH’ is set to the appropriate variable buttonStateX and that variable controls which light show plays in the control structure. If the loop reads every button as a ‘LOW’ then the default state is for the LED matrix to clear itself.

Continue reading LED Matrix – Code

LED Matrix – Big Picture

Team 6 Demo Video

The goal of the final project was to display 3 different patterns on a LED light matrix. Each display is triggered by the press of a button. The first display starts when the red button is pushed and displays the letters “ECE”, each individually, a nod to our team’s academic department. The second display is set by the blue button and shows the first initial of each team member’s name: M,H,K, and R. The final display is a light show and is triggered by pressing the white button.

For the project, our team utilized an Arduino Uno and code was written in the native Arduino environment. We designed and implemented a custom PCB for the LED matrix to ease the wiring and reduce wiring confusion. Each of the 64 LEDs were able to be placed and soldered into the PCB. Female to male headers were also placed and soldered in to easily allow connections to the Arduino Uno pins. One design challenge we encountered was keeping our design low power. In order to do so we made decisions such as using the lowest voltage LEDs possible, to stay within our design constraint.

LED Matrix – Schematics

Initial Schematic
PCB Layout

After determining the main goal of our final project, the team decided that the best possible way to create the LED Matrix was to use a custom PCB design. In our schematic above, the rating of the resistors utilized needed to be determined. By dividing the difference of the voltage of the LED from the voltage of the source by the current of the LED, we were able to determine that each row required a 150 Ohm resistor.

In creating the schematic and PCB, the program EasyEDA was employed. After all the components were placed on the schematic and properly laid out, the program’s native “Convert to PCB” added all of the components to a new PCB design file. The 64 LEDS were then properly spaced to be in the center of 1” squares. The traces were added to connect all the positive leads of the LEDS on the front side of the PCB. Additional traces were added, seen in blue in the PCB schematic, on the back side of the PCB to connect all the negative leads in the columns. In order to ease the wiring, 2 female to male header pin layouts were added.

Motion Sensor Jingle Player – Code

The code included a custom library we built, the Alarm library. The library contains functionality that lets users build their own Jingles to be played, as well as some built-in, default jingles.

The note() method

The main part of the Alarm library is the Jingle class’s note() method, which simplifies the process of playing tones for the user. The note() function makes use of the Arduino tone() and delay() functions. The tone() function outputs a specified frequency to a specified output pin for a specified duration. Since the tone() function doesn’t wait for the note to complete before moving onto the next command, the delay() function is called so that the notes can be properly spaced.

To let users make jingles more easily, different musical notes are pre-programmed. The notes are set to the corresponding frequency that the Arduino’s tone() function will use to play the note.

One of the preset alarms


Motion Sensor Jingle Player – Big Picture

The goal of this project is to create a motion detected alarm system with a button to turn the alarm on or off and toggle between different jingles.

When the PIR motion detector is triggered, a Honeytone speaker will play a jingle, controlled by a custom C++ library. The jingle won’t play if the alarm isn’t set; the user can tell because of an LED that is lit up when the alarm is on. The pushbutton, when long pressed, turns the alarm on or off; if short pressed, it will toggle between different preset jingles.

The project uses an Arduino board because of the built-in library to output single-frequency tones. Originally, the project also used interrupts, but it conflicted with the Arduino’s library; instead, logic for all inputs and outputs is handled within the loop() method.

The project was a success: the motion detector will trigger and the speaker play the selected jingle when the alarm is on, but won’t do anything when the alarm is off.

Basic Demonstration Video

Motion Sensor Jingle Player – Schematics

Motion detector
Cardboard walls

The final design made use of a PIR Motion Sensor. The sensor is powered to 5V, grounded, and connected to digital input pin 2 on the Arduino board. The motion sensor has two potentiometers on its side, one which controlled the sensitivity and another which controlled the delay between detection signals.

The motion detector is able to detect motion from across a room, which caused some issues with staying as still as possible while trying to test and eventually led to the design of cardboard walls for the sensor. The walls act as blinders to narrow the sensor’s detection range and simplifies testing. In a general purpose design, the walls would make sure the sensor only detects motion it’s supposed to.

Full Schematic

Simon Says – Code

This snippet was some of the most driving code within the Simon Says system. The randomized pattern generation to illuminate the LED’s was critical to operational success. Patterns could have been hard coded, but at the cost of efficiency and code readability.

Following the randomized pattern generation, this display function illustrates the initial step in reading user input. This “lock and key” mechanism (LED display and user input) ensures the advancement of progress throughout the game.