7/19/24 Balloon Launch from High Point State Park

Here is the data from our successful launch on 7/19/24. 

We launched at 12:16 pm from the Appalachian Trail head parking lot in High Point State Park, Sussex, NJ.

At 3:46 pm, 125 miles of flight later, the balloon landed in Bantam Lake, Bantam, CT.

Splashdown was witnessed by the ops team of Leonardo DRS from Danbury, CT, out on the lake for a boat day, who made the recovery.  A special thank you to Shae and the DRS ops team for saving the electronics from a watery grave!

Long Island in the distance.

Peak altitude: 24 km!!

The fork of Long Island.

Here is the complete flight video.  Note that the software cut out midway through the descent.  The problem is being investigated – it is possible the battery froze.

 

Balloon Code V4

import os
import picamera
import serial
import time
import board
import adafruit_bmp280
import RPi.GPIO as GPIO
import json
 
 
GPIO.setwarnings(False)
#GPIO.setmode(GPIO.BOARD)
GPIO.setup(18, GPIO.OUT, initial=GPIO.LOW)
 
i2c = board.I2C()
bmp = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)
bmp.sea_level_pressure = 1013.25
 
camera = picamera.PiCamera()
camera.resolution = (1280, 720)
camera.rotation = 180
framerate = 5
camera.framerate = framerate
camera.annotate_text_size = 18
 
gps = "GPS Data"
gpsPort = "/dev/ttyACM0"
gpsSerial = serial.Serial(gpsPort, baudrate = 9600, timeout = 0.5)
loggingObject = {
    'GPS':{
        'latitude':{
            'degrees': 0,
            'minutes': 0,
            'seconds': 0,
            'NS': 0
        },
        'longitude':{
            'degrees': 0,
            'minutes': 0,
            'seconds': 0,
            'EW': 0
        },
        'altitude': 0,
        'satellites': 0
    },
    'speed': 0,
    'altitude': 0,
    'time': '',
    'temperature': 0,
    'humidity': 0
}

def getPicture(annotation):
    filename = "/home/pi/Pictures/" + str(time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())) + ".jpg"
    try:
        camera.start_preview()
        time.sleep(2.5)
        camera.annotate_text = annotation
        camera.capture(filename)
        camera.stop_preview()
    except Exception as error:
        return(error)
        
        camera.stop_preview()
 
    return filename
 
def getVideo(length):
    filename = "/home/pi/Videos/" + str(time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())) + ".mp4"
    
    try:
        camera.start_recording("/home/pi/testVideo.h264")
 
        for index in range(length):
            start = time.time()
 
            camera.annotate_text = (annotate())
            
            end = time.time()
            
            elapsed = start - end
 
            if elapsed <= 1:
                time.sleep(1 - elapsed)
        
        camera.stop_recording()
    except Exception as error:
        return(error)
 
    os.system("ffmpeg -r " + str(framerate) + " -i /home/pi/testVideo.h264 -vcodec copy " + filename)
    os.system("del /home/pi/testVideo.h264")
    
    return filename
 
def gpgga():
    output = ""
    emailgps = ""
    try:
        n = 1
        while output == "" and n<50:
            gps = str(gpsSerial.readline())
            #print(n)
            if (gps[2:8] == "$GPGGA" or gps[2:8] == "$GNGGA"):
                gps = gps.split(",")
                #lat long formatted for digital maps
                latgps = gps[2][0:2] + ' ' + gps[2][2:]
                longgps = '-'+gps[4][1:3] + ' ' + gps[4][3:]
                emailgps = latgps+','+longgps
 
                latDeg = int(gps[2][0:2])
                latMin = int(gps[2][2:4])
                latSec = round(float(gps[2][5:9]) * (3/500))
                latNS = gps[3]
                output += "Latitude: " + str(latDeg) + " deg " + str(latMin) + "'" + str(latSec) + '" ' + latNS + "\n"
                
                longDeg = int(gps[4][0:3])
                longMin = int(gps[4][3:5])
                longSec = round(float(gps[4][6:10]) * (3/500))
                longEW = gps[5]
                output += "Longitude: " + str(longDeg) + " deg " + str(longMin) + "'" + str(longSec) + '" ' + longEW + "\n"
                
                alt = float(gps[9])
                output += "Altitude: " + str(alt) + " m" + "\n"
 
                sat = int(gps[7])
                output += "Satellites: " + str(sat)
                loggingObject['GPS'] = {
                    'latitude':{
                        'degrees': latDeg,
                        'minutes': latMin,
                        'seconds': latSec,
                        'NS': latNS
                    },
                    'longitude':{
                        'degrees': longDeg,
                        'minutes': longMin,
                        'seconds': longSec,
                        'EW': longEW
                    },
                    'altitude': alt,
                    'satellites': sat
                }
            n+=1
        return [output,emailgps]
    except Exception as error:
        return ["",""]
 
def gprmc():
    output = ""
    
    try:
        n = 1
        while output == "" and n<50:
            #print(n)
            gps = str(gpsSerial.readline())
            
            if gps[2:8] == "$GPRMC" or gps[2:8] == "$GNRMC":
                gps = gps.split(",")
 
                output = ""
 
                speed = round(float(gps[7]) * 1852)/1000
                loggingObject["speed"] = speed
                output += "Speed: " + str(speed) + " km/h"
            n+=1
        return output
        
    except Exception as error:
        return("")
 
def gps():
    try:
        output = gpgga()[0] + "\n" + gprmc()    
        return output
    except Exception as error:
        return("")
 
def accurate_altitude():
    try:
        output = 'BMP280 Altitude: {} m'.format(round(bmp.altitude))
        loggingObject['altitude'] = round(bmp.altitude)
        return output
    except Exception as error:
        return("")
 
def annotate():
    timeNow = str(time.strftime("%a %d %b %Y %H:%M:%S", time.localtime()))
    print(timeNow)
    locationNow = gps()
    bmpa = accurate_altitude()
    annotation = timeNow + "\n" + locationNow + "\n" + bmpa
    return annotation
 
def logData():
    try:
        loggingObject['time'] = time.time()
        filename = 'home/pi/loggedData/' + str(time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())) + '.json'
        writtenFile = open(filename,'w')
        writtenFile.write(json.dumps(loggingObject, sort_keys=True, indent=4))
        writtenFile.close()
    except Exception as error:
        pass


def flyBalloon():
    while True:
        try:      
            getVideo(10) #40
            GPIO.output(18, GPIO.HIGH)
            getPicture("")
            getPicture(annotate())
            logData()
            GPIO.output(18,GPIO.LOW)
        except Exception as error:
            return(error)
 
flyBalloon()

Advent of Code 2023-25a

import networkx as nx 
import matplotlib.pyplot as plt 
import re
floppy = open("input25.txt", mode='r', encoding='utf-8')
thing =  floppy.readlines()
floppy.close()
sourcenode = []

for i, word in enumerate(thing):
    sourcenode.append(word[0:3])
    thing[i] = word[4:].split()

visual = []
for i, source in enumerate(sourcenode):
    for dest in thing[i]:
        visual.append([source,dest])
G = nx.Graph()
G.add_edges_from(visual)

nx.draw_networkx(G) 
plt.show()
import networkx as nx 
import matplotlib.pyplot as plt 

G = nx.Graph()
G.add_edges_from([['a','b'],['b','c'],['a','c'],['s','u']])
nx.draw_networkx(G) 
plt.show()

Balloon Code V3

import os
import picamera
import serial
import time
import board
import adafruit_bmp280
import RPi.GPIO as GPIO


GPIO.setwarnings(False)
#GPIO.setmode(GPIO.BOARD)
GPIO.setup(18, GPIO.OUT, initial=GPIO.LOW)

i2c = board.I2C()
bmp = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)
bmp.sea_level_pressure = 1013.25

camera = picamera.PiCamera()
camera.resolution = (1280, 720)
camera.rotation = 180
framerate = 5
camera.framerate = framerate
camera.annotate_text_size = 18

gps = "GPS Data"
gpsPort = "/dev/ttyACM0"
gpsSerial = serial.Serial(gpsPort, baudrate = 9600, timeout = 0.5)

def getPicture(annotation):
    filename = "/home/pi/Pictures/" + str(time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())) + ".jpg"

    try:
        camera.start_preview()
        time.sleep(2.5)
        camera.annotate_text = annotation
        camera.capture(filename)
        camera.stop_preview()
    except Exception as error:
        return(error)
       
        camera.stop_preview()

    return filename

def getVideo(length):
    filename = "/home/pi/Videos/" + str(time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())) + ".mp4"
   
    try:
        camera.start_recording("/home/pi/testVideo.h264")

        for index in range(length):
            start = time.time()

            camera.annotate_text = (annotate())
           
            end = time.time()
           
            elapsed = start - end

            if elapsed <= 1:
                time.sleep(1 - elapsed)
       
        camera.stop_recording()
    except Exception as error:
        return(error)

    os.system("ffmpeg -r " + str(framerate) + " -i /home/pi/testVideo.h264 -vcodec copy " + filename)
    os.system("del /home/pi/testVideo.h264")
   
    return filename

def gpgga():
    output = ""
    emailgps = ""
    try:
        n = 1
        while output == "" and n<50:
            gps = str(gpsSerial.readline())
            #print(n)
            if (gps[2:8] == "$GPGGA" or gps[2:8] == "$GNGGA"):
                gps = gps.split(",")
                #lat long formatted for digital maps
                latgps = gps[2][0:2] + ' ' + gps[2][2:]
                longgps = '-'+gps[4][1:3] + ' ' + gps[4][3:]
                emailgps = latgps+','+longgps

                latDeg = int(gps[2][0:2])
                latMin = int(gps[2][2:4])
                latSec = round(float(gps[2][5:9]) * (3/500))
                latNS = gps[3]
                output += "Latitude: " + str(latDeg) + " deg " + str(latMin) + "'" + str(latSec) + '" ' + latNS + "\n"
               
                longDeg = int(gps[4][0:3])
                longMin = int(gps[4][3:5])
                longSec = round(float(gps[4][6:10]) * (3/500))
                longEW = gps[5]
                output += "Longitude: " + str(longDeg) + " deg " + str(longMin) + "'" + str(longSec) + '" ' + longEW + "\n"
               
                alt = float(gps[9])
                output += "Altitude: " + str(alt) + " m" + "\n"

                sat = int(gps[7])
                output += "Satellites: " + str(sat)
            n+=1
        return [output,emailgps]
    except Exception as error:
        return ["",""]

def gprmc():
    output = ""
   
    try:
        n = 1
        while output == "" and n<50:
            #print(n)
            gps = str(gpsSerial.readline())
           
            if gps[2:8] == "$GPRMC" or gps[2:8] == "$GNRMC":
                gps = gps.split(",")

                output = ""

                speed = round(float(gps[7]) * 1852)/1000
                output += "Speed: " + str(speed) + " km/h"
            n+=1
        return output
       
    except Exception as error:
        return("")

def gps():
    try:
        output = gpgga()[0] + "\n" + gprmc()
        return output
    except Exception as error:
        return("")

def accurate_altitude():
    try:
        output = 'BMP280 Altitude: {} m'.format(round(bmp.altitude))
        return output
    except Exception as error:
        return("")

def annotate():
    timeNow = str(time.strftime("%a %d %b %Y %H:%M:%S", time.localtime()))
    locationNow = gps()
    bmpa = accurate_altitude()
    annotation = timeNow + "\n" + locationNow + "\n" + bmpa
    return annotation


def flyBalloon():
    while True:
        try:      
            getVideo(10) #40
            GPIO.output(18, GPIO.HIGH)
            getPicture("")
            getPicture(annotate())
            GPIO.output(18,GPIO.LOW)
        except Exception as error:
            return(error)

flyBalloon()

Prim’s Algorithm Maze Generation

&lt;/div&gt;
# Maze generator -- Randomized Prim Algorithm

## Imports
import random
import time
from colorama import init
from colorama import Fore, Back, Style

## Functions
def printMaze(maze):
	for i in range(0, height):
		for j in range(0, width):
			if (maze[i][j] == 'u'):
				print(Fore.WHITE + str(maze[i][j]), end=" ")
			elif (maze[i][j] == 'c'):
				print(Fore.GREEN + str(maze[i][j]), end=" ")
			else:
				print(Fore.RED + str(maze[i][j]), end=" ")
			
		print('\n')

# Find number of surrounding cells
def surroundingCells(rand_wall):
	s_cells = 0
	if (maze[rand_wall[0]-1][rand_wall[1]] == 'c'):
		s_cells += 1
	if (maze[rand_wall[0]+1][rand_wall[1]] == 'c'):
		s_cells += 1
	if (maze[rand_wall[0]][rand_wall[1]-1] == 'c'):
		s_cells +=1
	if (maze[rand_wall[0]][rand_wall[1]+1] == 'c'):
		s_cells += 1

	return s_cells


## Main code
# Init variables
wall = 'w'
cell = 'c'
unvisited = 'u'
height = 11
width = 27
maze = []

# Initialize colorama
init(convert=True)

# Denote all cells as unvisited
for i in range(0, height):
	line = []
	for j in range(0, width):
		line.append(unvisited)
	maze.append(line)

# Randomize starting point and set it a cell
starting_height = int(random.random()*height)
starting_width = int(random.random()*width)
if (starting_height == 0):
	starting_height += 1
if (starting_height == height-1):
	starting_height -= 1
if (starting_width == 0):
	starting_width += 1
if (starting_width == width-1):
	starting_width -= 1

# Mark it as cell and add surrounding walls to the list
maze[starting_height][starting_width] = cell
walls = []
walls.append([starting_height - 1, starting_width])
walls.append([starting_height, starting_width - 1])
walls.append([starting_height, starting_width + 1])
walls.append([starting_height + 1, starting_width])

# Denote walls in maze
maze[starting_height-1][starting_width] = 'w'
maze[starting_height][starting_width - 1] = 'w'
maze[starting_height][starting_width + 1] = 'w'
maze[starting_height + 1][starting_width] = 'w'

while (walls):
	# Pick a random wall
	rand_wall = walls[int(random.random()*len(walls))-1]

	# Check if it is a left wall
	if (rand_wall[1] != 0):
		if (maze[rand_wall[0]][rand_wall[1]-1] == 'u' and maze[rand_wall[0]][rand_wall[1]+1] == 'c'):
			# Find the number of surrounding cells
			s_cells = surroundingCells(rand_wall)

			if (s_cells < 2):
				# Denote the new path
				maze[rand_wall[0]][rand_wall[1]] = 'c'

				# Mark the new walls
				# Upper cell
				if (rand_wall[0] != 0):
					if (maze[rand_wall[0]-1][rand_wall[1]] != 'c'):
						maze[rand_wall[0]-1][rand_wall[1]] = 'w'
					if ([rand_wall[0]-1, rand_wall[1]] not in walls):
						walls.append([rand_wall[0]-1, rand_wall[1]])


				# Bottom cell
				if (rand_wall[0] != height-1):
					if (maze[rand_wall[0]+1][rand_wall[1]] != 'c'):
						maze[rand_wall[0]+1][rand_wall[1]] = 'w'
					if ([rand_wall[0]+1, rand_wall[1]] not in walls):
						walls.append([rand_wall[0]+1, rand_wall[1]])

				# Leftmost cell
				if (rand_wall[1] != 0):	
					if (maze[rand_wall[0]][rand_wall[1]-1] != 'c'):
						maze[rand_wall[0]][rand_wall[1]-1] = 'w'
					if ([rand_wall[0], rand_wall[1]-1] not in walls):
						walls.append([rand_wall[0], rand_wall[1]-1])
			

			# Delete wall
			for wall in walls:
				if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
					walls.remove(wall)

			continue

	# Check if it is an upper wall
	if (rand_wall[0] != 0):
		if (maze[rand_wall[0]-1][rand_wall[1]] == 'u' and maze[rand_wall[0]+1][rand_wall[1]] == 'c'):

			s_cells = surroundingCells(rand_wall)
			if (s_cells < 2):
				# Denote the new path
				maze[rand_wall[0]][rand_wall[1]] = 'c'

				# Mark the new walls
				# Upper cell
				if (rand_wall[0] != 0):
					if (maze[rand_wall[0]-1][rand_wall[1]] != 'c'):
						maze[rand_wall[0]-1][rand_wall[1]] = 'w'
					if ([rand_wall[0]-1, rand_wall[1]] not in walls):
						walls.append([rand_wall[0]-1, rand_wall[1]])

				# Leftmost cell
				if (rand_wall[1] != 0):
					if (maze[rand_wall[0]][rand_wall[1]-1] != 'c'):
						maze[rand_wall[0]][rand_wall[1]-1] = 'w'
					if ([rand_wall[0], rand_wall[1]-1] not in walls):
						walls.append([rand_wall[0], rand_wall[1]-1])

				# Rightmost cell
				if (rand_wall[1] != width-1):
					if (maze[rand_wall[0]][rand_wall[1]+1] != 'c'):
						maze[rand_wall[0]][rand_wall[1]+1] = 'w'
					if ([rand_wall[0], rand_wall[1]+1] not in walls):
						walls.append([rand_wall[0], rand_wall[1]+1])

			# Delete wall
			for wall in walls:
				if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
					walls.remove(wall)

			continue

	# Check the bottom wall
	if (rand_wall[0] != height-1):
		if (maze[rand_wall[0]+1][rand_wall[1]] == 'u' and maze[rand_wall[0]-1][rand_wall[1]] == 'c'):

			s_cells = surroundingCells(rand_wall)
			if (s_cells < 2):
				# Denote the new path
				maze[rand_wall[0]][rand_wall[1]] = 'c'

				# Mark the new walls
				if (rand_wall[0] != height-1):
					if (maze[rand_wall[0]+1][rand_wall[1]] != 'c'):
						maze[rand_wall[0]+1][rand_wall[1]] = 'w'
					if ([rand_wall[0]+1, rand_wall[1]] not in walls):
						walls.append([rand_wall[0]+1, rand_wall[1]])
				if (rand_wall[1] != 0):
					if (maze[rand_wall[0]][rand_wall[1]-1] != 'c'):
						maze[rand_wall[0]][rand_wall[1]-1] = 'w'
					if ([rand_wall[0], rand_wall[1]-1] not in walls):
						walls.append([rand_wall[0], rand_wall[1]-1])
				if (rand_wall[1] != width-1):
					if (maze[rand_wall[0]][rand_wall[1]+1] != 'c'):
						maze[rand_wall[0]][rand_wall[1]+1] = 'w'
					if ([rand_wall[0], rand_wall[1]+1] not in walls):
						walls.append([rand_wall[0], rand_wall[1]+1])

			# Delete wall
			for wall in walls:
				if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
					walls.remove(wall)


			continue

	# Check the right wall
	if (rand_wall[1] != width-1):
		if (maze[rand_wall[0]][rand_wall[1]+1] == 'u' and maze[rand_wall[0]][rand_wall[1]-1] == 'c'):

			s_cells = surroundingCells(rand_wall)
			if (s_cells < 2):
				# Denote the new path
				maze[rand_wall[0]][rand_wall[1]] = 'c'

				# Mark the new walls
				if (rand_wall[1] != width-1):
					if (maze[rand_wall[0]][rand_wall[1]+1] != 'c'):
						maze[rand_wall[0]][rand_wall[1]+1] = 'w'
					if ([rand_wall[0], rand_wall[1]+1] not in walls):
						walls.append([rand_wall[0], rand_wall[1]+1])
				if (rand_wall[0] != height-1):
					if (maze[rand_wall[0]+1][rand_wall[1]] != 'c'):
						maze[rand_wall[0]+1][rand_wall[1]] = 'w'
					if ([rand_wall[0]+1, rand_wall[1]] not in walls):
						walls.append([rand_wall[0]+1, rand_wall[1]])
				if (rand_wall[0] != 0):	
					if (maze[rand_wall[0]-1][rand_wall[1]] != 'c'):
						maze[rand_wall[0]-1][rand_wall[1]] = 'w'
					if ([rand_wall[0]-1, rand_wall[1]] not in walls):
						walls.append([rand_wall[0]-1, rand_wall[1]])

			# Delete wall
			for wall in walls:
				if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
					walls.remove(wall)

			continue

	# Delete the wall from the list anyway
	for wall in walls:
		if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
			walls.remove(wall)
	


# Mark the remaining unvisited cells as walls
for i in range(0, height):
	for j in range(0, width):
		if (maze[i][j] == 'u'):
			maze[i][j] = 'w'

# Set entrance and exit
for i in range(0, width):
	if (maze[1][i] == 'c'):
		maze[0][i] = 'c'
		break

for i in range(width-1, 0, -1):
	if (maze[height-2][i] == 'c'):
		maze[height-1][i] = 'c'
		break

# Print final maze
printMaze(maze)

Recipe Hax

Hello Hacker Gentlemen.

Below are the 3 pieces of code we have at the moment.  Your task is to edit the allrecipes.py code to make it more useful.  At current, it creates an enormous list of completely unsorted recipes, and is functionally equivalent to throwing a box with thousands of recipe cards into a pile on the floor.  You are now going to add some sorting to this to make it more useful.  In total, your changes will probably be no more than 2-3 lines of code in allrecipes.py.  Use regular expressions to, for example, create a separate text file for recipes that contain the word “pie” in the title.  That is just one possibility, the sorting criteria is entirely up to you!  If you would like to review/finish the lessons on the regex website, click here.

import re
#re stands for regular expressions
sentence = "The rain in Spain ComPLaiN, 8ain ain't 5ai9t ai"
# 01234567891111111
# 0123456

x = re.search("ai", sentence)

print(x.span())
# . is the metacharacter for any character (except for newline)
#[a-z] represents any lower case alpha character
#[A-Z] represents any upper case alpha character
#[0-9] represents any numeric character
#\w represents "word" characters, a-z, A-Z, 0-9, _ underscore
#\W represents anything that is NOT a "word" character
#\s string contains a whitespace character (space, tab, newline, return, feed)
#\S anything that is not a whitespace character
#* represents any number of the thing it follows
x = re.findall('[\w]*ai[\w]*',sentence)
print(x)
import requests, time, re
from recipe_scrapers import scrape_me
f = open("last_recipe_checked.txt",'rt')
content = f.readlines()  
start = int(content[-1])
f.close()
currentrecipe = start
def main():    
    validrecipes = []
    for i in range(start,9999999):
        f = open("last_recipe_checked.txt",'w')########
        f.write(str(i)+'\n')########
        f.close() ########
        url = 'https://cooking.nytimes.com/recipes/' + str(i)
        time.sleep(0.25)
        if requests.get(url).status_code == 200:
            currentrecipe = i
            recipe = scrape_me(url,wild_mode = True)
            print(recipe.title(),i)
            f = open("nytimesrecipes.txt","at")
            f.write(recipe.title() + "     " + url + '\n')
            f.close()
            validrecipes += [i]
if (__name__ == "__main__"):
    main()
 import requests, time
import requests, time
import shutil
from recipe_scrapers import scrape_me
url = 'https://cooking.nytimes.com/recipes/103'
recipe = scrape_me(url,wild_mode = True)
image_url = recipe.image()
file_name = recipe.title() + ' image.jpg'
res = requests.get(image_url, stream = True)
if res.status_code == 200:
    with open(file_name,'wb') as f:
        shutil.copyfileobj(res.raw, f)
    print('Image sucessfully Downloaded: ',file_name)
else:
    print('Image Couldn\'t be retrieved')
##################################################
from fpdf import FPDF
pdf = FPDF(orientation='P', unit = 'in', format = 'letter')
pdf.add_page()
pdf.set_xy(0.0,0.0)
pdf.set_font('Arial','B',16)
pdf.set_text_color(0,0,0)
pdf.cell(w=8.5,h=1.0, align = 'C', txt = recipe.title(), border = 0)
pdf.image(file_name, x = 2.75, y = 1, w = 3, h = 3, type = 'jpg', link = '')
pdf.set_font('Arial','',12)
pdf.set_text_color(0,0,0)
x = 4
for ingredient in recipe.ingredients():
    pdf.cell(w=3.5,h=.25, align = 'L', txt = ingredient, border = 0)
    x += 0.25
    pdf.set_xy(1.0,x)
x+=1
pdf.set_xy(1.0,x)
pdf.multi_cell(w=7,h=0.25, align = 'L', txt = recipe.instructions(), border = 0)
pdf.output(file_name+'.pdf','F')