AI Vs the Black Death: Building a Medieval Doctor Machine

by Ranvi25 in Circuits > Microcontrollers

161 Views, 2 Favorites, 0 Comments

AI Vs the Black Death: Building a Medieval Doctor Machine

FEV9A0QMNGJRYXT.jpg
unnamed.jpg

What if you could visit a doctor during the Black Death?

In this project, I built a fully interactive Medieval AI Doctor Simulator using an ESP32 and a TFT display. Using only two buttons, the device guides the user through a diagnosis process and delivers results based on both historical beliefs and modern medical understanding.

With animated analysis, a risk detection system, and a clean interface, this project recreates how people once understood disease — and contrasts it with what we know today.

A mix of history, electronics, and “AI-like” logic — all in one device.

This Project falls under the Middle-Ages category.

Supplies

Before starting, make sure you have all the required parts:

  1. ESP32 microcontroller
  2. TFT display (ILI9341 SPI)
  3. 2 push buttons
  4. Breadboard-(ESP32 wide breadboard or use 2 with a gap)
  5. Jumper wires

Wire the TFT Display

F3T6EAQMNGJRYXQ.jpg

Connect your TFT display to the ESP32 using SPI:

  1. VCC → 3.3V
  2. GND → GND
  3. CS → GPIO 5
  4. RESET → GPIO 4
  5. DC → GPIO 2
  6. MOSI (SDI) → GPIO 23
  7. SCK → GPIO 18
  8. LED → 3.3V
  9. MISO (optional) → GPIO 19

Make sure all connections are secure, as loose wires can cause display issues.

Connect the Buttons

Each button connects between a GPIO pin and ground:

  1. Button 1 → GPIO 25 → GND
  2. Button 2 → GPIO 26 → GND

The ESP32 uses internal pull-up resistors, so no external resistors are needed.

Install and Configure the Display Library

  1. Open Arduino IDE
  2. Go to Library Manager
  3. Install the TFT_eSPI library

Then configure it:

  1. Open User_Setup.h
  2. Enable:
#define ILI9341_DRIVER
  1. Set your pins:
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 5
#define TFT_DC 2
#define TFT_RST 4
#define TFT_MISO 19

Save the file before continuing.

Upload the Code

Upload the main program to your ESP32.

Once uploaded, the display should turn on and show the main menu.

If the screen stays blank:

  1. Check wiring
  2. Confirm correct driver (ILI9341)
  3. Restart Arduino IDE

Using the Device

The interface is controlled using only two buttons:

  1. Button 1 → Scroll up
  2. Button 2 → Scroll down
  3. Hold Button 1 → Select

The system will guide you through:

  1. Selecting a symptom
  2. Choosing duration
  3. Choosing severity

AI Diagnosis Process

unnamed.jpg

After entering inputs, the system:

  1. Simulates analysis with animated screens
  2. Displays a progress bar
  3. Generates a diagnosis based on a decision system

It evaluates:

  1. Symptom type
  2. Duration
  3. Severity

Then assigns a risk level:

  1. Low Risk
  2. Medium Risk
  3. High Risk

Understanding the Results

The device presents:

  1. Risk level
  2. Medieval treatment (historically accurate)
  3. Modern medical explanation

This highlights the contrast between past and present medical knowledge.

Final Thoughts

This project demonstrates how a simple microcontroller can simulate intelligent behavior through structured logic.

It also provides an engaging way to explore how medical understanding has evolved over time.

Full Code

#include <TFT_eSPI.h>


TFT_eSPI tft = TFT_eSPI();


const int btnUp = 26; // swapped

const int btnDown = 25;


int step = 0;

int selection = 0;


unsigned long pressStart = 0;

bool holding = false;


// Data

String symptoms[] = {"Fever", "Cough", "Black Spots"};

String duration[] = {"1-2 days", "3-5 days", "1+ week"};

String severity[] = {"Mild", "Severe"};


int maxItems[] = {3, 3, 2};


int s, d, sev;


String titles[] = {"Symptom?", "Duration?", "Severity?"};


// ===== STARTUP =====

void startupScreen() {

tft.fillScreen(TFT_BLACK);


String title = "PLAGUE AI";


tft.setTextSize(3);

tft.setTextColor(TFT_RED);

tft.setCursor(40, 60);


for (int i = 0; i < title.length(); i++) {

tft.print(title[i]);

delay(150);

}


tft.setTextSize(2);

tft.setTextColor(TFT_WHITE);

tft.setCursor(60, 110);

tft.println("Initializing...");


tft.drawRect(20, 180, 280, 20, TFT_WHITE);


for (int i = 0; i <= 280; i += 10) {

tft.fillRect(20, 180, i, 20, TFT_RED);

delay(40);

}


delay(300);


tft.fillScreen(TFT_RED);

delay(120);

tft.fillScreen(TFT_BLACK);


tft.setTextColor(TFT_GREEN);

tft.setCursor(30, 120);

tft.println("System Ready");


delay(800);

}


// ===== UI =====

void drawUI() {

tft.fillScreen(TFT_BLACK);


tft.setTextSize(2);

tft.setTextColor(TFT_CYAN);

tft.setCursor(10, 10);

tft.println("PLAGUE AI SCANNER");


tft.setTextColor(TFT_WHITE);

tft.setCursor(10, 50);

tft.println(titles[step]);


tft.fillRoundRect(20, 100, 280, 60, 8, TFT_WHITE);

tft.setTextColor(TFT_BLACK);

tft.setCursor(40, 120);

tft.println(getOption());


tft.setTextColor(TFT_YELLOW);

tft.setCursor(10, 200);

tft.println("Hold UP to select");

}


String getOption() {

if (step == 0) return symptoms[selection];

if (step == 1) return duration[selection];

if (step == 2) return severity[selection];

return "";

}


// ===== THINKING =====

void thinkingText() {

String msgs[] = {

"Scanning symptoms...",

"Comparing records...",

"Checking infection...",

"Evaluating risk..."

};


for (int i = 0; i < 4; i++) {

tft.fillScreen(TFT_BLACK);

tft.setCursor(20, 120);

tft.setTextColor(TFT_GREEN);

tft.setTextSize(2);

tft.println(msgs[i]);

delay(600);

}

}


// ===== PROGRESS =====

void progressBar() {

tft.fillScreen(TFT_BLACK);


tft.setTextColor(TFT_GREEN);

tft.setCursor(40, 40);

tft.println("Analyzing Patient");


for (int i = 0; i <= 100; i += 5) {

tft.drawRect(20, 120, 280, 20, TFT_WHITE);

tft.fillRect(20, 120, i * 2.8, 20, TFT_GREEN);


tft.setCursor(120, 160);

tft.println(String(i) + "%");


delay(70);

}

}


// ===== SUMMARY =====

void showSummary() {

tft.fillScreen(TFT_BLACK);


tft.setTextSize(2);

tft.setTextColor(TFT_WHITE);


tft.setCursor(10, 20);

tft.println("Patient Summary:");


tft.println("\nSymptom: " + symptoms[s]);

tft.println("Duration: " + duration[d]);

tft.println("Severity: " + severity[sev]);


delay(2000);

}


// ===== RESULT =====

void showResult() {

tft.fillScreen(TFT_BLACK);


int risk = 0;


if (s == 2) risk += 2;

if (sev == 1) risk += 2;

if (d == 2) risk += 1;


tft.setTextSize(2);

tft.setCursor(10, 20);


if (risk >= 4) {

tft.setTextColor(TFT_RED);

tft.println("HIGH RISK\n");

tft.setTextColor(TFT_WHITE);

tft.println("Likely PLAGUE\n");

tft.println("Medieval:");

tft.println("Quarantine\nLeeches\n");

tft.println("Modern:");

tft.println("Bacterial infection\nAntibiotics");

}

else if (risk >= 2) {

tft.setTextColor(TFT_ORANGE);

tft.println("MEDIUM RISK\nPossible illness");

}

else {

tft.setTextColor(TFT_GREEN);

tft.println("LOW RISK\nMinor condition");

}


tft.setTextColor(TFT_YELLOW);

tft.setCursor(10, 220);

tft.println("Hold UP to restart");

}


// ===== SETUP =====

void setup() {

pinMode(btnUp, INPUT_PULLUP);

pinMode(btnDown, INPUT_PULLUP);


tft.init();

tft.setRotation(1);


startupScreen();

drawUI();

}


// ===== LOOP =====

void loop() {


if (digitalRead(btnUp) == LOW && digitalRead(btnDown) == HIGH && !holding) {

selection--;

if (selection < 0) selection = maxItems[step] - 1;

drawUI();

delay(200);

}


if (digitalRead(btnDown) == LOW && digitalRead(btnUp) == HIGH) {

selection++;

if (selection >= maxItems[step]) selection = 0;

drawUI();

delay(200);

}


if (digitalRead(btnUp) == LOW && digitalRead(btnDown) == HIGH) {


if (!holding) {

pressStart = millis();

holding = true;

}


tft.setCursor(10, 230);

tft.setTextColor(TFT_GREEN);

tft.println("Selecting...");


if (millis() - pressStart > 800) {


if (step == 0) s = selection;

if (step == 1) d = selection;

if (step == 2) sev = selection;


step++;

selection = 0;

holding = false;


if (step > 2) {

thinkingText();

progressBar();

showSummary();

showResult();

delay(5000);

step = 0;

}


drawUI();

delay(300);

}


} else {

holding = false;

}

}