Introduction: Learn Python to Cut Pie With Π (Pi) Using a Raspberry Pi!

Have you ever found yourself in the sticky situation of cutting enough pieces of pie just perfectly for all your guests :) There is that dreaded, "My piece is smaller then yours!" comment. Well no more, this ingenious invention will measure pie pieces using the brilliant ratio of the circumference of any circle using a Raspberry PI!

Spirit of Design:This project is an introduction to the GIPO pins of a Raspberry pie, and is a great way to learn some Python tricks and a few hardware components that can be used for so many other projects. In this project we used mathematical PI - 3.14 to generate many of the parts and code along with the Raspberry Pi to build a fun and interactive project. Feel free to remix and post:)

Supplies

General Supplies:

(1) Raspberry Pi board (Any version - Prefer Pi 4)

(1) MicroSD card (with at least 16 GB recommended)

(1) Power supply (Micro USB)

(1) 3D Pinter - Any printer works you can even try and contact individuals on: https://www.reddit.com/r/3Dprintmything

(1) Python editing software (Geany or Text) editor.

(1) HDMI cable

(1) soldering iron

(1 roll) solder


Project Specific:

(2) Packages of Laser Diodes 4 in total. It is important to purchase the (Laser Line) filter diodes.

(1) SG90 Micro Servo Motor

(1) IIC/I2C/TWI LCD 1602 LCD Display Serial Interface Adapter Module Blue Backlight

(1 pk) Female to Male Multicolored Ribbon Cables

(1 Roll) 24 Gauge awg black and red wire

(1) Button or Joy Stick Breakout Module (MCP 3008) Analog-to-Digital Converter (ADC) needed

(1) 10k Resistor (button debounce)

(1) A T-cobbler board (optional)

(1) Breadboard (400 points breadboard)(optional)

(1) 10 Small Shrink Wrap tubes

(1) Zip Tie :)

Step 1: Setting Up Pi for LCD Display & Wiring

First: Its is important to understand how to interface with GPIO pins. GPIO stands for General-Purpose Input/Output. These are effectively input and output pins similar to other micro-controllers like Arduino and Micro:bits. They represent the ability to perform digital and analog operations like switching and sensor reading.

For the purpose of this project we will be using the Raspberry Pi (3) or any version coupled with a LCD screen, Laser Diodes and a push button. All of these items could be used to make tons of other great projects. Most electronics can interface with the Raspberry PI directly but if you are trying to use electronics that draw more current then (16 mA) or (5.0 volts)you will need to use a relay or transistor to prevent board damage.

Warning: As always ensure that you have made all proper connections prior to turning on your Raspberry Pi and that you use a consistent ground. Poor ground has wasted many an hour of "Fun" Instructable creation time.

Prior to installing any of LCD software connect the required 4 wires to the LCD using the following pins.

- Connect VCC (power) to the 5V pin (pin 4)

- Connect GND (ground) to any GND pin (pin 6)

- Connect SDA (data) to GPIO 2 (pin 3)

- Connect SCL (clock) to GPIO 3 (pin 5)

Step 2: Assemble the Laser Heads

The leads on the laser diodes are rather short so for this project you will need to solider approximately 16" on the red leads of the lasers and approximately six inches to the black leads. Insert each laser diode into the head connectors. Some adjustments may be needed to the fitment depending on how your printer creates rafts or a baseplate.

Step 3: Single Ground Lead

Once soldiered then connect the black leads together to a single ground wire.

Step 4: Assembling the Base

Assemble the base by sliding the flat bar "Adjustable Stand 2" into the "Laser Head" as shown below. Connect the base to the "Final Adjustable Stand" as pictured. Slide the stand into place.

Step 5: Setting Up the Laser Heads

Next you will need to install the lasers heads as pictures and then zip tie the heads into place along with the wiring as pictured.

Step 6: Installing LCD Software

  1. We need to configure the pi for IC2/GPIO interfaces. If you are not using a 4 wire display some of these steps may required more wiring and a few changes to the commands.
  2. sudo raspi-config
  3. select option (3) - Interface Options
  4. select (I5) - IC2
  5. <yes>
  6. <finish>
  7. Next check to ensure everything was properly installed.
  8. lsmod | grep i2c
  9. You must reboot to initialize the interfaces.
  10. sudo reboot
  11. Next we need a few necessary library tools.
  12. sudo apt-get install -y i2c-tools python3-smbus
  13. Next ensure that the LCD is connected. A grid will display showing the address of the LCD (27).
  14. sudo i2cdetect -y 1
  15. In order to use Python LCD packages we will need to install a library.
  16. sudo pip3 install RPLCD smbus2
  17. If all goes well you can open any editor including Geany and add the following example code.
  18. Save as "lcd_test.py" and execute with: python3 lcd_test.py

from RPLCD.i2c import CharLCD
lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1, cols=16, rows=2, dotsize=8)
lcd.clear()
lcd.write_string('Hello, World!')

Step 7: Setting Up the Laser Diodes/Leds

Next: As stated earlier GPIO pins can be either inputs or outputs. In order to use this feature you must first import the GPIO package. import RPi.GPIO as GPIO. In order to designate time for actions to occur, you also need to import the time package import time.

Next setup the push buttonto the following pins.

- Connect 10k resistor from GPIO 17 (pin 11) to GND (pin 9)

- Connect a momentary push button from 3v3 (pin 1) to GPIO 17 (pin 11)

Note: A GPIO pin designated as an output or input pin can be set to read or write high at (3.3V) or low (0V). In our case the laser diodes are 3v so they can be directly controlled by the Raspberry Pi.

  1. Connect the positive red power leads to the lasers to pins (18, 23, 24, 25).
  2. Connect the negative black leads to the lasers to pins (GND).
  3. Using Geany create a test file called "laser_test.py" using the code below and test to see that each laser lights and then turns off.
  4. Note: the use of a PYTHON ARRAY here to iterate through the values this is a great technique to reduce typos and set all pins to outputs and to low so that they are off. By default the Pi sets pins to inputs.
lasers = [18,23,24,25]
for x in lasers:
GPIO.setup(x,GPIO.OUT)
GPIO.output(x,GPIO.LOW

File Name: laser_test.py

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Define output pins and set them low
lasers = [18,23,24,25]
for x in lasers:
GPIO.setup(x,GPIO.OUT)
GPIO.output(x,GPIO.LOW)

for i in range(1, 6):
time.sleep(5)
for x in lasers:
GPIO.output(x,GPIO.HIGH)
time.sleep(5)
for x in lasers:
GPIO.output(x,GPIO.LOW)

Step 8: Debounce Settings With Buttons

Note: No (ADC) Converter :( I originally intended to control the screen with a joystick however the Raspberry Pi does not have an analog to digital converter and I want to keep this fun without allot of hardware. If you are interested in using a Joy Stick with Raspberry Pi, you will need to use one of the following chips [ADC0834, AD57830, MCP3008 & MCP3002]. For this project we have chosen to go with a single button and a 10k resistor to pull down the pin. This creates what is called denounce cycle to prevent accidental miss reads by the Raspberry Pi. Later we will be using a single push button to cycle through the values of a users selection option using denounce code.

Debounce: Debouncing Buttons is removing unwanted input noise from buttons or switches or other user input to prevent clicks that a program might not actually receive. To do this a 10k resistor is connected to ground from the input pin and used to bring the pins voltage to zero.

	import RPi.GPIO as GPIO
from time import sleep

button = 17
preState = False
GPIO.setmode(GPIO.BCM)
GPIO.setup(button,GPIO.IN)

while True:
buttonValue = GPIO.input(button)
if buttonValue == True:
preState = not preState
print ("button 1 is pressed")
while GPIO.input(button) == True:
pass
#Increase this value to slow down button reads
sleep(0.5)

Step 9: Putting It Together

Next Step: Now we want to put it all together. Using the button and LCD and lasers we can loop though a PYTHON HASHMAP/Dictionary Object and or select a value from a key.

# Loop through the key and get the value to set to low and output
for x,v in lasers.items():
GPIO.setup(v,GPIO.OUT)
GPIO.output(v,GPIO.LOW)

Python code to select a value based on a key:


for x,v in lasers.items():
GPIO.output(v,GPIO.LOW)

For every selected pie amount each laser will be selected to turn on. The user will get confirmation of the setting on the LCD screen.

File Name: pie_cutter.py

from RPLCD.i2c import CharLCD
import RPi.GPIO as GPIO
from time import sleep

button = 17
i = 2
# Create a dictionary of GPIO ports
lasers = {'2': 18,'4': 23,'6': 24,'8': 25}

preState = False
GPIO.setmode(GPIO.BCM)
GPIO.setup(button,GPIO.IN)
GPIO.setwarnings(False)
# Loop through the key and get the value to set to low and output
for x,v in lasers.items():
GPIO.setup(v,GPIO.OUT)
GPIO.output(v,GPIO.LOW)

lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1, cols=16, rows=2, dotsize=8)
lcd.write_string('Pie Size Slicer')

while True:
buttonValue = GPIO.input(button)
if buttonValue == True:
# Reset all lasers to off if back at 2
if i == 2:
for x,v in lasers.items():
GPIO.output(v,GPIO.LOW)
print (str(i) + " button is pressed")
lcd.clear()
lcd.write_string('Pie Size Slicer')
# Allows you to write on the second line of the display
lcd.crlf()
lcd.write_string(str(i)+' : slices')
# Use the key selected to get the value from the dictionary
GPIO.output(lasers.get(str(i)),GPIO.HIGH)
i = i+2
if i > 8:
i = 2
preState = not preState
while GPIO.input(button) == True:
pass
sleep(0.5)

Step 10: Final Set Setting Up a Service

  1. One of the best ways to have a program run is as a service. This allows the Raspberry Pi to boot properly and if any issues occur with the service it will terminate with an error log.
  2. I have included a great article about it By: Diego Acuña
  3. First declare the use of python3 in the header of the above file:
#!/usr/bin/python
  1. sudo su
cd /lib/systemd/system/
sudo nano pie.service
  1. Edit the file with the following information. You will need to change your path as necessary.
[Unit]
Description=Pie Cutting Service
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/piwithpi/pie_cutter.py
Restart=on-abort

[Install]
WantedBy=multi-user.target


  1. Use Ctrl+O and ENTER to save Crtl+X to exit
  2. Next activate the service with the following commands:
  3. sudo chmod 644 pie.service
  4. chmod +x /home/piwithpi/pie_cutter.py
  5. sudo systemctl daemon-reload
  6. sudo systemctl enable pie.service
  7. sudo systemctl start pie.service

  8. Reboot and see if you have a working service!
  9. To work on your program you will need to stop it:
  10. sudo systemctl stop pie.service

Step 11: PI - GEEK OUT TIME

EXPERT MODE PI PART!! Feel Free to Remix

In the Sprit of the contest we wanted to used "Matplotlib" in Python to calculate the points where the lasers angle needs to adjust based on height to create intersecting points. The intent was to have the lasers rotate to their positions to intersect at various heights. Perhaps this will be in another Instructable. We must first install all the python library. A few libraries like Numpy and Math are already installed so there is no need to install them. The below simulation will use Python and PI to locate the points where the lasers would potentially rotate and angle. Happy Constructing!

  1. sudo apt install python3-matplotlib
  2. num_sections - indicates the selected sections provide by user input
# Specify the number of sections and radius
num_sections = 6
circumference = 31.42 # You can adjust the circumference here


The below code takes the number of sections and the circumferences and then determines a series of points surrounding the circle from that location.


import matplotlib.pyplot as plt
import numpy as np
import math

# Specify the number of sections and radius
num_sections = 6
circumference = 31.42 # You can adjust the circumference here

def plot_circle_sections(num_sections, circumference):
# Generate angles for the sections
angles = np.linspace(0, 360,
num_sections + 1) # Linspace divides the first two parameters evenly by the section numbers

# Plot the circle
fig, ax = plt.subplots()
ax.set_aspect('equal', adjustable='box') # Define the aspect ratio of the Grid
circle = plt.Circle((0, 0), radius, edgecolor='black', facecolor='none') # Define the circle
ax.add_artist(circle) # draw the circle on the Grid

# Plot the sections and their intersection points with the circle
intersection_points = []
for i in range(num_sections):
theta = np.radians(angles[i]) # Use the evenly spaced angled values and covert the value to radians
x = radius * np.cos(theta) # Claculate the x and y of each space
y = radius * np.sin(theta) # Calculate the y and y of each space
ax.plot([0, x], [0, y], 'b-') # Plot line from center to circle boundary
intersection_points.append((x, y)) # put each point in the array above

# Annotate with angle measure
angle_diff = angles[i + 1] - angles[i] # Calculates the angle diffrence
angle_text = f'{angle_diff:.0f}°' # Format the Text
angle_mid = (angles[i] + angles[i + 1]) / 2 # Formats Angle measure in middle
ax.text(radius * 0.7 * np.cos(np.radians(angle_mid)), radius * 0.7 * np.sin(np.radians(angle_mid)), angle_text,
ha='center', va='center')

# Plot intersection points and annotate with coordinates
for i, point in enumerate(intersection_points):
ax.plot(point[0], point[1], 'ro') # Plot intersection point
ax.annotate(f'({point[0]:.2f}, {point[1]:.2f})', (point[0], point[1]), textcoords="offset points",
xytext=(5, 5), ha='center')

plt.xlim(-1.1 * radius,
1.1 * radius) # add a gap between the edges of the grid and circle(ENSURES FULL CIRCLE STAYS ON GRID)
plt.ylim(-1.1 * radius, 1.1 * radius)
plt.title(f"Circle divided into {num_sections} equal sections with radius {radius}") # Grid Title
plt.grid(True) # Display grid
plt.show() # Show all

radius = circumference / (2 * math.pi) # calculate radius off of your pie using pi
# Plot the circle divided into equal sections with intersection points, coordinates, and angle measures
plot_circle_sections(num_sections, radius)
All Things Pi Contest

This is an entry in the
All Things Pi Contest