Final Coding Prompts¶
I brought it code that I made before playing with the webserver and some code I wrote with McWhorter.
PROMPT: Using this photosensor to web app code, I want to take the buttons out of this code and then integrate in a way to message or email to text someone if the pill has not been take (i.e. the light is not bright again). I have the light sensor inverted so i need to fix also.
CLAUDE: reminded met hat we dont use stepper.h with the A4988. Then asked about how we wanted to do the messaging and gave me some options
| Method | Cost | Setup complexity | Reliability | Notes |
|---|---|---|---|---|
| Email (Gmail SMTP) | Free | Medium | Good | Needs app password; can go to spam; slow |
| SMS via Twilio | ~$0.01/msg | Medium | Excellent | Needs account + credit card; very reliable |
| Telegram bot | Free | Easy | Excellent | Needs Telegram app; instant delivery |
| Pushover | $5 one-time | Easy | Excellent | Best push notification app; clean UI |
Telegram¶
We had a discussion about texting with Telegram which we cant do directly.. but Claude said it wouldnt be hard to migrate to email to text if we start with Telegram. So I chose to start with Telegram. and Claude gave me these steps
Let's go with Telegram then — it's genuinely simpler to set up on the ESP32 side (no library needed, just one HTTPS GET), and if you want SMS later you just swap the function. Verizon noted for if you switch. Here's what you'll need to do before I write the code — takes about 3 minutes:
- Install Telegram on your phone if you don't have it
- Search for BotFather inside Telegram → send /newbot → follow prompts → it gives you a bot token (looks like 123456:ABCdef...)
- Search for userinfobot inside Telegram → send it /start → it gives you your chat ID (a number)
- Start a conversation with your new bot (search its name, hit Start)
You'll paste the token and chat ID into the code as constants.
PROMPT: yes, write code, but I want to understand it so I can work on sections
Here you go:
The logic flow:
- Scheduled time hits → motor turns to dispense pill
- Wait a window (e.g. 30 min) → check if light sensor sees bright light (pill removed)
- If no bright light detected → send Telegram alert
- Light sensor fix → invert the comparison so "bright = pill taken"
The five sections we'll restructure:
[1] CONFIG — WiFi, Telegram token/chatID, pins, timing constants
[2] MOTOR — moveWheel() using A4988 STEP/DIR on GPIO22/21
[3] LIGHT SENSOR — readLight(), isPillTaken() with corrected logic
[4] NOTIFICATION — sendTelegram() — the one swappable function
[5] SCHEDULER — checks time, triggers dispense, starts check window, fires alert
The web server and NTP code from your original stays mostly the same — we just add the new sections around it.
Then Claude gave me a bunch of code with good comments.
The key things to tune before first test:
LIGHT_THRESHOLD = 2000— open your browser tohttp://<IP>/lightstatuswith and without something blocking the sensor, note the two readings, and pick a threshold in betweenSTEPS_PER_DISPENSE = 256— adjust until your wheel turns the right amount- Put your actual Telegram token and chat ID in Section 1
Suggested testing order:
- Check
/lightstatusraw readings first (Section 4) - Use "Dispense Now" button to test motor (Section 3)
- Set a 1-minute window and test the full alert flow (Section 6)
PROMPT: I want the light to come on when the pill is dispensed and stay on until its taken. its on GPIO4 and its connected to 3.3v with a resistor so it should be default high , and then go low to turn on.
CLaude wrote some more code and then gave the following instructions:
The main things to do before first flash:
- Get your Telegram credentials — BotFather for the token, userinfobot for your chat ID, paste both into Section 1
- Tune the light threshold — flash as-is, open http://
/lightstatus in your browser, note the reading with pill present vs absent, pick a number between them and update LIGHT_THRESHOLD - Tune STEPS_PER_DISPENSE — hit the "Dispense Now" button and adjust until the wheel turns the right amount
The steps before dispense I know from my other stepper motor work.. its 25 per dispense. The Telegram stuff, I did... the Light threshold instructions, I needed a bit more help to understand.
PROMPT: Explain to me how this work? and I upload my code and then do this? Remind me where I get the IP address - was it in the serial monitor.. "open your browser to http://
/lightstatus with and without something blocking the sensor, note the two readings, and pick a threshold in between"
How the web server works:
The ESP32 is running a tiny web server, just like a website server but on your desk. When it boots and connects to WiFi, it gets assigned an IP address on your local network (like 192.168.1.47). Any device on the same WiFi — your phone, laptop, etc. — can open a browser and talk to it.
The routes like /lightstatus, /dispense, /status are just URLs. When your browser visits http://192.168.1.47/lightstatus, the ESP32 runs handleLightStatus() and sends back a text response. That's all it is.
The flow from flash to tuning:
1. Paste your WiFi credentials into Section 1
2. Flash the code via Arduino IDE / PlatformIO
3. Open Serial Monitor at 115200 baud
4. Watch it connect to WiFi — it will print:
Connected! IP: 192.168.1.XX ← this is your IP
5. Copy that IP address
6. On your laptop/phone (same WiFi network), open browser:
http://192.168.1.XX/lightstatus
Tuning the light threshold:
Once you're on that page, it shows something like:
Raw ADC: 312 | Threshold: 2000 | Pill taken: YES
Do it twice:
- No pill / open light → note the number (e.g. 312)
- Block the sensor with your hand → note the number (e.g. 3100)
Pick a number halfway between — in this example 1700. Update LIGHT_THRESHOLD = 1700 in Section 1, reflash, and the sensor logic will be correctly calibrated.
You only need to do this tuning once — unless you change your lighting conditions or rewire the sensor.
PROMPT: can we change code to send message sooner.. so then they get a message as soon as the pill is there.. and then another if the pill is still there after x minutes
CLAUDE: That way they know to go take it, and the second message is the nudge if they forgot. Only two changes needed to dispenseOnePill() and checkPillWindow() — the rest of the code stays identical. In dispenseOnePill() — add one line:
void dispenseOnePill() {
Serial.println("Dispensing pill...");
moveWheel(STEPS_PER_DISPENSE);
digitalWrite(LED_PIN, LOW);
pillDispensed = true;
pillCheckActive = true;
alertSent = false;
dispenseTime = millis();
// NEW: immediate notification
sendTelegram("Your pill is ready to take!");
Serial.println("Pill dispensed. Notification sent.");
}
checkPillWindow() stays exactly the same — it already sends the reminder when the window expires.
This also gives you a way to test Telegram immediately — hit Dispense Now and you should get the first message within a few seconds, before any window logic runs.
That'll confirm your credentials and connection are working.