Goodday & Turtlex
Hey Goodday, I’ve been working on a little open‑source hack that turns a regular coffee machine into a programmable art studio. You can script it to blend beans, tweak temperatures, even add a splash of a new flavor on the fly—kind of like a creative espresso palette. Curious to see what quirky coffee‑art combo we could pull together?
Wow, that sounds absolutely wild! I can already picture a neon swirl latte that changes colors as the brew steams up. Maybe throw in some cinnamon dust and a splash of matcha to give it that green glow? Or how about a little “rainbow foam” layer that pops when the coffee hits the cup? Let’s hack it into a little script that lets you pick a “mood” and the machine mixes up the beans, temperature, and a secret flavor secretively… just like a living art piece. What’s the first vibe you’re thinking of?
I’m thinking of starting with a “Midnight Ember” vibe. Deep dark roast, a lower brew temperature so the espresso stays rich, a pinch of cinnamon dust for that warm spice, and a splash of activated charcoal‑infused syrup to give the foam a subtle midnight blue glow. The script would load a JSON profile, set the grinder, adjust the pump timing, and trigger a foam‑spiking valve when the espresso hits the cup. It’s a bit of a labyrinth, but that’s the fun part—building a mood‑setting brew machine that feels like a living painting.
That sounds like the coolest midnight rave your kitchen can host! Dark roast, low heat, cinnamon fire, and charcoal glow—like a smoky moon in a cup. I’d add a little glittery sugar rim to catch that blue light too. This coffee studio is going to be the next big art exhibit. Ready to code the magic?
Sure thing, let’s sketch the core in Python with a Raspberry Pi and a 3‑phase solenoid controller. First, a JSON for the vibe:
```
{
"name":"Midnight Ember",
"beans":"dark roast",
"temperature":85,
"cinnamon":1,
"charcoal_syrup":2,
"foam_spike":true,
"rim_glitter":"blue"
}
```
Then a script that:
1. Reads the profile,
2. Sends grinder torque and grind time via GPIO,
3. Controls the pump speed through PWM to hit the target temperature,
4. Activates the foam valve on espresso flow,
5. Triggers a small LED strip for the charcoal glow,
6. Sprinkles the rim sugar with a micro‑servo.
We’ll keep the logic in a single `brew.py` file, use `RPi.GPIO` for hardware, and `json` for profiles. Want to dive into the exact GPIO pins or the timing math?
Sounds epic! Let’s go with pin 17 for the grinder motor, 27 for the grinder timer relay, 22 for the pump PWM, 23 for the foam valve, 24 for the LED strip, and 25 for the sugar servo. For timing, keep the grinder on for about 1.5 seconds per gram of beans, then let the pump run at 60% duty cycle until the brew temp hits 85 °C, then pop the foam valve for 0.8 seconds. You can tweak the duty cycle in real time by reading the temp sensor loop. Ready to code it up?
Got it. Here’s a quick skeleton you can drop into `brew.py`. It keeps everything in one place and lets you tweak the duty cycle while it’s running.
```python
import RPi.GPIO as GPIO
import time
import json
from Adafruit_DHT import read_retry, DHT22, DHT11 # or any temp sensor you use
GPIO.setmode(GPIO.BCM)
# Pin assignments
GRINDER_MOTOR = 17
GRINDER_TIMER = 27
PUMP_PWM = 22
FOAM_VALVE = 23
LED_STRIP = 24
SUGAR_SERVO = 25
# Setup
GPIO.setup(GRINDER_MOTOR, GPIO.OUT)
GPIO.setup(GRINDER_TIMER, GPIO.OUT)
GPIO.setup(PUMP_PWM, GPIO.OUT)
GPIO.setup(FOAM_VALVE, GPIO.OUT)
GPIO.setup(LED_STRIP, GPIO.OUT)
GPIO.setup(SUGAR_SERVO, GPIO.OUT)
pump = GPIO.PWM(PUMP_PWM, 1000) # 1 kHz PWM
pump.start(60) # start at 60% duty cycle
servo = GPIO.PWM(SUGAR_SERVO, 50) # 50 Hz servo
servo.start(0)
def load_profile(name):
with open('profiles.json') as f:
data = json.load(f)
return data[name]
def grind(grams, grind_time_sec):
GPIO.output(GRINDER_TIMER, GPIO.HIGH)
time.sleep(grind_time_sec * grams)
GPIO.output(GRINDER_TIMER, GPIO.LOW)
def heat_to_temp(target):
while True:
# replace with your sensor read logic
temp = read_retry(DHT22, 4)[0] # dummy, use real sensor
if temp >= target:
break
# adjust duty cycle if you want auto‑tune
# pump.ChangeDutyCycle(60) # keep static for now
time.sleep(0.1)
def foam_pop():
GPIO.output(FOAM_VALVE, GPIO.HIGH)
time.sleep(0.8)
GPIO.output(FOAM_VALVE, GPIO.LOW)
def rim_glitter():
# simple pulse on the LED strip to catch the rim light
GPIO.output(LED_STRIP, GPIO.HIGH)
time.sleep(0.2)
GPIO.output(LED_STRIP, GPIO.LOW)
def main():
profile = load_profile('Midnight Ember')
grind(profile['cinnamon'] + 1, 1.5) # 1.5s per gram + cinnamon dust
heat_to_temp(profile['temperature'])
pump.ChangeDutyCycle(60) # could be dynamic
foam_pop()
rim_glitter()
# servo to sprinkle sugar – a quick 180° pulse
servo.ChangeDutyCycle(7.5) # mid‑position
time.sleep(1)
servo.ChangeDutyCycle(12.5) # up
time.sleep(1)
servo.ChangeDutyCycle(0) # stop
pump.stop()
servo.stop()
GPIO.cleanup()
if __name__ == "__main__":
main()
```
Just adjust the sensor part to your real temperature module, and you’re set. Happy brewing!
Nice, that’s a solid first cut! Just remember to swap out the dummy `read_retry` with whatever temp module you’re actually using – a DS18B20 or a thermocouple will give you the real degrees. I’d also wrap the whole thing in a `try / finally` block so the GPIO always cleans up even if something crashes. Maybe add a quick sanity check that the grinder isn’t stuck, and give the user a tiny “brew complete” LED or sound. With those tweaks, you’ll have a midnight‑emerging espresso machine that feels like a living painting. Happy hacking!