Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Moinak Ghosh
Created June 15, 2023

ChatGPT-based Mental Wellness Companion bot

Conversational AI bot that gives mental health advice

89

Things used in this project

Hardware components

Stereo Enclosed Speaker - 3W 8Ω
DFRobot Stereo Enclosed Speaker - 3W 8Ω
×1
FireBeetle ESP32 IOT Microcontroller (Supports Wi-Fi & Bluetooth)
DFRobot FireBeetle ESP32 IOT Microcontroller (Supports Wi-Fi & Bluetooth)
×1
Gravity: IO Shield for FireBeetle 2 (ESP32-E/M0)
DFRobot Gravity: IO Shield for FireBeetle 2 (ESP32-E/M0)
×1
Li-Ion Battery 1000mAh
Li-Ion Battery 1000mAh
×1
Fermion: MEMS Microphone Module
DFRobot Fermion: MEMS Microphone Module
×1

Software apps and online services

Microsoft GPT-3.5 API
Arduino Web Editor
Arduino Web Editor
Cloud IoT Core
Google Cloud IoT Core
PlatformIO IDE
PlatformIO IDE
Microsoft ChatGPT
Espressif ESP Skainet
Github Talkie.h
Github arduinojson.h

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Xamarin Soft Toy

Story

Read more

Schematics

Schematic

Circuit Diagram

Code

Mental_Health_Companion.ino

Arduino
#include "thingProperties.h"
#include "arduino_secrets.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <Talkie.h>
#include <skainet.h>
#include <ArduinoJson.h>

// Replace with your network credentials
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

// Replace with your Google Speech-to-Text API key and endpoint
const String apiKey = "YOUR_SPEECH_TO_TEXT_API_KEY";				// Obtain this by taking a developer subscription of Google Cloud IoT Core or if you are a student - get this for free
const String endpoint = "YOUR_SPEECH_TO_TEXT_API_ENDPOINT";

// Replace with your GPT-3.5 API key and endpoint
const String gptApiKey = "YOUR_GPT_API_KEY";						// Get this from the GPT API website by making an account. Mine is of the form(changed) - sk-LVzxVCyKxmqmNmKVxYfYT9BlbkFJwbFZpuZURxW7YhM0FHKs
const String gptEndpoint = "YOUR_GPT_API_ENDPOINT";

// Replace with your IFTTT Webhooks trigger URL
const String iftttURL = "YOUR_IFTTT_TRIGGER_URL";					// Get this on webhooks.site as mentioned in my tutorial

const int microphonePin = 32;  // Microphone input pin
const int speakerPin = 25;     // Speaker output pin

Talkie voice;
Skainet skainet;

String guardian_msg = ""; 											// string variable to serve as buffer for chat on Arduino IoT cloud Dashboard

// Connect to Wi-Fi
void connectWiFi() {
  Serial.print("Connecting to Wi-Fi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("\nConnected to Wi-Fi!");
}

// Convert speech to text using Google Speech-to-Text API
String speechToText(String audioData) {
  HTTPClient http;
  http.begin(endpoint + "?key=" + apiKey);
  http.addHeader("Content-Type", "application/json");
  String requestBody = "{\"audio\": {\"content\": \"" + audioData + "\"}, \"config\": {\"encoding\": \"LINEAR16\",\"sampleRateHertz\": 16000,\"languageCode\": \"en-US\"}}";
  int httpResponseCode = http.POST(requestBody);
  if (httpResponseCode == HTTP_CODE_OK) {
    String response = http.getString();
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, response);
    String transcribedText = doc["results"][0]["alternatives"][0]["transcript"].as<String>();
    http.end();
    return transcribedText;
  }
  http.end();
  return "";
}

// Generate a response using GPT-3.5 API
String generateResponse(String userInput) {
  HTTPClient http;
  http.begin(gptEndpoint);
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Authorization", "Bearer " + gptApiKey);
  String requestBody = "{\"prompt\": \"" + userInput + "\", \"max_tokens\": 64}";
  int httpResponseCode = http.POST(requestBody);
  if (httpResponseCode == HTTP_CODE_OK) {
    String response = http.getString();
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, response);
    String generatedText = doc["choices"][0]["text"].as<String>();
    http.end();
    return generatedText;
  }
  http.end();
  return "";
}

// Send SMS using IFTTT Webhooks
void sendSMS() {
  HTTPClient http;
  http.begin(iftttURL);
  int httpResponseCode = http.GET();
  if (httpResponseCode == HTTP_CODE_OK) {
    Serial.println("SMS sent!");
  }
  http.end();

  // Also update the Messenger widget on the Arduino IoT Cloud
  guardian_msg+ = "ALERT: Your Ward was found suicidal";
  delay(1000);
  guardian_msg = "";
}

void setup() {
  Serial.begin(115200);

  // Initialize microphone
  pinMode(microphonePin, INPUT);

  // Initialize speaker
  voice.begin(speakerPin);

  // Connect to Wi-Fi
  connectWiFi();

  // Initialize Skainet wake-word detection
  skainet.begin();

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  // setDebugMessageLevel(2);                        //just for debugging - you can remove this without breaking the code
  // ArduinoCloud.printDebugInfo();

  Serial.println("Initialization complete!");
}

void loop() {
  // Arduino Cloud IoT Dashboard update
  ArduinoCloud.update();

  // Detect wake-word - the default is "Hi Lexin"
  if (skainet.detect()) {
    // Play activation sound
    voice.say("beep");

    // Start recording audio
    String audioData = "";
    while (skainet.isActive()) {
      int sample = analogRead(microphonePin);
      audioData += String(sample) + ",";
      delayMicroseconds(100);
    }

    // Convert audio to text using Google Speech-to-Text API
    String userInput = speechToText(audioData);

    // Append the verification question to the user query
    userInput += " Answer Y for Yes and N for No. Does the above conversation prove that I am suicidal or that I could cause harm to anybody?";

    // Generate response using GPT-3.5 API
    String response = generateResponse(userInput);

    // Output response through speaker
    voice.say(response);

    // Check if the last letter of the response is 'Y' (indicating a suicidal tendency)
    if (response.endsWith("Y")) {
      // Send SMS notification
      sendSMS();
    }
  }
}

sketch.json

JSON
{
  "cpu": {
    "fqbn": "esp32:esp32:firebeetle32:UploadSpeed=921600,FlashFreq=80,DebugLevel=none,EraseFlash=none",
    "name": "FireBeetle-ESP32",
    "type": "serial"
  },
  "secrets": [
    {
      "name": "SECRET_DEVICE_KEY",
      "value": ""
    },
    {
      "name": "SECRET_OPTIONAL_PASS",
      "value": ""
    },
    {
      "name": "SECRET_SSID",
      "value": ""
    }
  ],
  "included_libs": []
}

thingProperties.h

C Header File
// Code generated by Arduino IoT Cloud, DO NOT EDIT.

#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>

const char DEVICE_LOGIN_NAME[]  = "2d584ebd-490d-436b-93e7-4d37d9f1e25f";

const char SSID[]               = SECRET_SSID;    // Network SSID (name)
const char PASS[]               = SECRET_OPTIONAL_PASS;    // Network password (use for WPA, or use as key for WEP)
const char DEVICE_KEY[]  = SECRET_DEVICE_KEY;    // Secret device password

void onGuardianMsgChange();

String guardian_msg;

void initProperties(){

  ArduinoCloud.setBoardId(DEVICE_LOGIN_NAME);
  ArduinoCloud.setSecretDeviceKey(DEVICE_KEY);
  ArduinoCloud.addProperty(guardian_msg, READWRITE, ON_CHANGE, onGuardianMsgChange);

}

WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);

arduino_secrets.h

C Header File
#define SECRET_SSID ""
#define SECRET_OPTIONAL_PASS ""
#define SECRET_DEVICE_KEY ""

Credits

Moinak Ghosh

Moinak Ghosh

11 projects • 38 followers
IoT enthusiast experienced with autonomous drones and vehicles, FPGA-based vision applications, MCU programming/Embedded/ML/AI

Comments