#define BLYNK_TEMPLATE_ID "TMPL5WL1EWOTo"
#define BLYNK_TEMPLATE_NAME "Bitcoin Price Tracker"
#define BLYNK_AUTH_TOKEN "ftpOjWK1Uue-vLIVHVR-ibUAl6ttbyP6"
#include <WiFi.h>
#include <WebServer.h>
#include <BlynkSimpleEsp32.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Adafruit_SSD1306.h>
// ===== WiFi =====
const char* ssid = "Wokwi-GUEST";
const char* pass = "";
// ===== AI API =====
const char* OPENAI_KEY = "b453666eb3d04c1fa7c608375d88f7fc";
const char* AI_URL = "https://artificialintelligence.openai.azure.com/openai/deployments/test/chat/completions?api-version=2023-05-15";
// ===== OLED =====
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// ===== LEDs =====
#define GREEN_LED_PIN 26
#define RED_LED_PIN 25
// ===== Server =====
WebServer web(80);
// ===== Variables =====
float priceHistory[10] = {0};
int historyIndex = 0;
float previousPrice = 0.0;
String lastAI = "No summary yet.";
int fetchCount = 0;
// ====== Animation ======
void animateBitcoinTracker() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
for (int x = SCREEN_WIDTH; x >= 10; x -= 5) {
display.clearDisplay();
display.setCursor(x, 20);
display.print("BITCOIN");
display.setCursor(x, 40);
display.print("TRACKER");
display.display();
delay(50);
}
delay(1000);
display.clearDisplay();
display.display();
}
// ====== Fetch Bitcoin Data ======
void fetchBitcoinData() {
HTTPClient http;
http.begin("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd");
int httpCode = http.GET();
if (httpCode == 200) {
DynamicJsonDocument doc(512);
deserializeJson(doc, http.getString());
float bitcoinPrice = doc["bitcoin"]["usd"];
// === Update history ===
priceHistory[historyIndex] = bitcoinPrice;
historyIndex = (historyIndex + 1) % 10;
fetchCount++;
// === OLED Display (last 2) ===
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Last Prices:");
for (int i = 0; i < 2; i++) {
int idx = (historyIndex - 1 - i + 10) % 10;
if (priceHistory[idx] == 0) continue;
int y = 15 + i * 20;
display.setCursor(0, y);
display.print("$");
display.print(priceHistory[idx], 2);
if (i == 0 && priceHistory[idx] > previousPrice) display.fillRect(100, y, 20, 10, SSD1306_WHITE);
else if (i == 0 && priceHistory[idx] < previousPrice) display.drawRect(100, y, 20, 10, SSD1306_WHITE);
}
display.display();
// === LED indicator ===
if (bitcoinPrice > previousPrice) {
digitalWrite(GREEN_LED_PIN, HIGH);
digitalWrite(RED_LED_PIN, LOW);
} else if (bitcoinPrice < previousPrice) {
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, HIGH);
} else {
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
}
previousPrice = bitcoinPrice;
http.end();
// === Every 10th fetch → ask AI ===
if (fetchCount % 10 == 0) {
String trendPrompt = "Last 10 Bitcoin prices: ";
for (int i = 0; i < 10; i++) {
trendPrompt += String(priceHistory[i]) + ", ";
}
trendPrompt += "Provide a short summary of current market mood (bullish, bearish, neutral).";
askAI(trendPrompt);
}
} else {
Serial.println("Error fetching Bitcoin data!");
}
http.end();
}
// ====== Ask AI ======
void askAI(String prompt) {
HTTPClient http;
http.begin(AI_URL);
http.addHeader("Content-Type", "application/json");
http.addHeader("api-key", OPENAI_KEY);
DynamicJsonDocument req(1024);
req["model"] = "gpt-3.5-turbo";
JsonArray messages = req.createNestedArray("messages");
JsonObject sys = messages.createNestedObject();
sys["role"] = "system";
sys["content"] = "You are a financial assistant. Be concise.";
JsonObject usr = messages.createNestedObject();
usr["role"] = "user";
usr["content"] = prompt;
String body;
serializeJson(req, body);
int code = http.POST(body);
if (code == 200) {
DynamicJsonDocument resp(2048);
deserializeJson(resp, http.getString());
lastAI = resp["choices"][0]["message"]["content"].as<String>();
} else {
lastAI = "AI fetch error.";
}
http.end();
}
// ====== Web Interface ======
void pageDashboard() {
String html = R"rawliteral(
<!DOCTYPE html><html><head><meta charset='utf-8'>
<title>Bitcoin Tracker</title>
<style>
body { font-family:Arial; background:#111; color:#fff; }
table { border-collapse:collapse; margin-top:10px; width:80%; }
td,th { padding:6px 10px; border:1px solid #444; text-align:center; }
.up { background:#2ecc71; }
.down { background:#e74c3c; }
.same { background:#555; }
</style></head><body>
<h1>₿ Bitcoin Tracker</h1>
<table><tr><th>#</th><th>Price (USD)</th></tr>
)rawliteral";
for (int i = 0; i < 10; i++) {
int idx = (historyIndex - 1 - i + 10) % 10;
float curr = priceHistory[idx];
float prev = priceHistory[(idx - 1 + 10) % 10];
String cls = "same";
if (curr > prev) cls = "up";
else if (curr < prev) cls = "down";
html += "<tr class='" + cls + "'><td>" + String(10 - i) + "</td><td>$" + String(curr, 2) + "</td></tr>";
}
html += "</table><h3>AI Market Summary:</h3><p>" + lastAI + "</p>";
html += "</body></html>";
web.send(200, "text/html", html);
}
// ====== Setup ======
void setup() {
Serial.begin(115200);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS);
animateBitcoinTracker();
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(300);
Serial.print(".");
}
Serial.println("\nWiFi connected!");
web.on("/", pageDashboard);
web.begin();
}
// ====== Loop ======
void loop() {
web.handleClient();
fetchBitcoinData();
delay(5000);
}