I roast coffee at home regularly. I haven’t updated my roasting log, I need a more lazy man approach to converting it all nicely. But I still do roast, and I use the neatest, dumb script ever..which I know works on OpenBSD and Linux. And it’s public domain
#!/usr/bin/env sh
COFFEEDIR="$HOME/Documents/coffeeroasts"
echo "Coffee country of origin?"; read origin
mkdir -p "$COFFEEDIR/$origin"
filecount=$(ls "$COFFEEDIR/$origin" | wc -l | xargs)
start_timer()
{
terms="xterm konsole gnome-terminal xfce4-terminal mate-terminal rxvt urxvt xterm-256color"
if [ $(command -v xterm) ]; then
xterm -e sh ./timer.sh &
elif [ $(command -v gnome-terminal) ]; then
gnome-terminal -- sh ./timer.sh &
fi
}
seconds_to_ts()
{
TIME=$1
if [ $(uname | grep -c "BSD") -eq 1 ]; then
date -u -r $TIME +%T
elif [ $(uname) = "Linux" ]; then
date -d @${TIME} +%T
fi
}
configure_roast()
{
echo "What is the coffee's name?"; read coffeename
dirname=$(echo $coffeename | sed 's/ /_/g')
roastdir="$COFFEEDIR/$origin/$dirname"
mkdir -p "$roastdir"
}
write_details()
{
START="$1"
DETAILS="$2"
FILE="$3"
#timefromstart=$(($(date +%s) - $START))
timefromstart=$(expr $(date +%s) - $START)
#printtime=$(date -u -r $timefromstart +%T)
printtime=$(seconds_to_ts $timefromstart)
echo "$printtime $DETAILS"
echo "$printtime $DETAILS" >> "$FILE"
}
calculate_phases()
{
START="$1"
ROASTFILE="$2"
drop=$(grep "TAG:DROP" "$ROASTFILE" | awk '{print $3}')
#roasttotal=$((($drop - $START)))
roasttotal=$(expr $drop - $START)
drystart=$(grep "TAG:DRY" "$ROASTFILE" | awk '{print $3}')
#drytime=$((($drystart - $START)))
drytime=$(expr $drystart - $START)
drypercent=$(echo $(echo "scale=2; $drytime/$roasttotal" | bc -l)*100 | bc)
onecrackstart=$(grep "TAG:1CSTART" "$ROASTFILE" | awk '{print $3}')
#browningtotal=$((($onecrackstart - $drystart)))
browningtotal=$(expr $onecrackstart - $drystart)
browningpercent=$(echo $(echo "scale=2; $browningtotal/$roasttotal" | bc -l)*100 | bc)
#developtotal=$((($drop - $onecrackstart)))
developtotal=$(expr $drop - $onecrackstart)
developpercent=$(echo $(echo "scale=2; $developtotal/$roasttotal" | bc -l)*100 | bc)
echo "Roast complete at $(date +%T) in $(seconds_to_ts $roasttotal) minutes"
echo "Roast complete at $(date +%T) in $(seconds_to_ts $roasttotal) minutes" >> "$ROASTFILE"
echo "Dry time: $(seconds_to_ts $drytime)\t\t\tDry time percent: $drypercent"
echo "Dry time: $(seconds_to_ts $drytime)\t\t\tDry time percent: $drypercent" >> "$ROASTFILE"
echo "Caramelization time: $(seconds_to_ts $browningtotal)\t\tCaramelization percent: $browningpercent"
echo "Caramelization time: $(seconds_to_ts $browningtotal)\t\tCaramelization percent: $browningpercent" >> "$ROASTFILE"
echo "Develop time: $(seconds_to_ts $developtotal)\t\t\tDevelop percent: $developpercent"
echo "Develop time: $(seconds_to_ts $developtotal)\t\t\tDevelop percent: $developpercent" >> "$ROASTFILE"
}
if [ $filecount -eq 0 ]; then
configure_roast
else
ls "$COFFEEDIR/$origin" | nl
echo "Are you roasting any of these? Pick the number or any other key for no"; read pickroast
dirname=$(ls "$COFFEEDIR/$origin" | nl | grep " $pickroast" | awk '{print $2}')
if [ -z "$dirname" ]; then
configure_roast
else
roastdir="$COFFEEDIR/$origin/$dirname"
fi
fi
start=$(date +%F)
roastfile="$roastdir/$start.txt"
touch "$roastfile"
echo "Batch size?" ; read batchsize
echo "Batch weight $batchsize" >> "$roastfile"
echo "Press any key to start the roast timer"; read x
startepoch=$(date +%s)
#xtimer &
start_timer
timer_pid=$!
echo "Enter 1 to note end of drying phase"
echo "Enter 2 to note start of 1 crack"
echo "Enter 3 to note end of roast"
echo "Enter q to exit the program entirely"
while read detail; do
case "$detail" in
q)
break
exit
;;
1)
write_details $startepoch "TAG:DRY $(date +%s)" "$roastfile"
continue
;;
2)
write_details $startepoch "TAG:1CSTART $(date +%s)" "$roastfile"
continue
;;
3)
write_details $startepoch "TAG:DROP $(date +%s)" "$roastfile"
break
;;
*)
write_details $startepoch "$detail" "$roastfile"
continue
;;
esac
done
calculate_phases $startepoch "$roastfile"
#pkill xtimer
if [ -z $timer_pid ]; then
pkill timer.sh
else
kill $timer_pid
fi
echo "Final roast size?" ; read finalbatchsize
echo "Drop weight: $finalbatchsize" >> "$roastfile"
startbatchnum=$(echo $batchsize | sed 's/g//g')
endbatchnum=$(echo $finalbatchsize | sed 's/g//g')
percentloss=$(echo "100*(1-($endbatchnum/$startbatchnum))" | bc -l)
printf "Weight percent loss: %.2f\n" $percentloss >> "$roastfile"
grep "TEMP" "$roastfile" | awk '{print $1" " $3}' | sed 's/C//g' > temp.dat
cat graphit.gp | gnuplot
graphfile="$roastfile-graph.png"
rm temp.dat
mv temps.png "$graphfile"
It’s pretty dumb, but works great. I roast with a BocaBoca250 so I have no
way to input data in except to watch the thermometer and do my best.
This script is nice because you can select the coffee origin, the name of the
coffee you are roasting, batch size, then input information you want such as
roaster settings, smells, etc. The part that matters is temperature entry. For
example, TEMP 100
, TEMP 180
, etc. Then numbers 1,2,3 for different phases
-
Dry phase finish
-
First crack start
-
Roast done
Looking at the contents here, you can see how I entered the values. I didn’t enter the times though. That is handle automatically as you enter temperatures and such.
When done, it calculates the time and percentages in dry phase, caramelization phase, and development phase, and lets you enter the final weight which will get you the % of moisture loss while roasting. Lastly, with gnuplot installed you will get a nice graph too like in the above post.
The last 2 scripts needed are timer.sh
#!/usr/bin/env sh
seconds_to_ts()
{
TIME=$1
if [ $(uname | grep -c "BSD") -eq 1 ]; then
date -u -r $TIME +%H:%M:%S
elif [ $(uname) = "Linux" ]; then
date -d @${TIME} +%H:%M:%S
fi
}
start=$(date +%s)
while true; do
time="$(($(date +%s) - $start))"
printf '%s\r' "$(seconds_to_ts $time)"
done
and graphit.gp
#!/usr/bin/env gnuplot
set terminal png size 800,600
set output "temps.png"
set xdata time
set timefmt "%H:%M:%S"
set title "Roasting Temperature Profile"
set xlabel "Minutes/seconds"
set ylabel "Temperature (C)"
set key below
set grid
plot "temp.dat" using 1:2 title "Time" with lines
Very basic and dumb but I’ve had fun using it the last year, and it has helped me make consistent roasts.
#100DaysToOffload #Post3