Jorge Eldis González
Published © CC BY

The Stoic Buddy: A Pocket Philosopher

A small desk companion inspired by Stoic philosophy that helps you pause, reflect, and face difficult moments calmly.

IntermediateFull instructions provided2 hours143
The Stoic Buddy: A Pocket Philosopher

Things used in this project

Hardware components

DFRobot Unihiker K10
×1

Software apps and online services

PlatformIO IDE
PlatformIO IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

Custom Case for Unihiker K10

Schematics

Unihiker K10 - Circuitry

Code

main.cpp

Arduino
#include "unihiker_k10.h"
#include "asr.h"
#include "StoicResponses.h"

void commands();
void philosopher(String emotion);
void answer(String msg);
void showCommands();

UNIHIKER_K10 k10;
Music music;
ASR asr;
uint8_t screen_dir = 2;
int idle = 0;
bool musicStop = false;
bool sleepingstate = false;
String neutral = "S:/philosopher192x192.png";
String happy = "S:/philosopherhappy192x192.png";
String sad = "S:/philosophersad192x192.png";
String sleeping = "S:/philosophersleeping192x192.png";
String talking = "S:/philosophertalking192x192.png";
String think = "S:/philosopherthink192x192.png";

void setup()
{
  k10.begin();
  randomSeed(analogRead(A0));
  int randomgreeting = random(0, 3);
  asr.asrInit(ONCE, EN_MODE, 6000);
  delay(2000);
  commands();
  k10.initScreen(screen_dir);
  k10.creatCanvas();
  k10.initSDFile();
  k10.setScreenBackground(0xebddab);
  k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
  philosopher(neutral);
  k10.canvas->canvasRectangle(20, 230, 205, 80, 0x8A3F35, 0xebddab, false);
  answer(StoicResponses::greetings[randomgreeting]);
  k10.canvas->updateCanvas();
}
void loop()
{
  idle++;
  delay(1000);
  if ((k10.buttonA->isPressed()))
  {
    showCommands();
  }
  if ((k10.buttonB->isPressed()))
  {
    idle = 0;
    int randomgreeting = random(0, 3);
    k10.canvas->canvasClear();
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(neutral);
    k10.canvas->canvasRectangle(20, 230, 205, 80, 0x8A3F35, 0xebddab, false);
    answer(StoicResponses::greetings[randomgreeting]);
    k10.canvas->updateCanvas();
  }
  if (asr.isDetectCmdID(1))
  {
    k10.canvas->canvasClear();
    int randomhappy = random(0, 3);
    int randomhappyrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::happyness[randomhappy]);
    delay(1000);
    answer(StoicResponses::happynessrecom[randomhappyrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(happy);
    idle = 0;
  }

  if (asr.isDetectCmdID(2))
  {
    k10.canvas->canvasClear();
    int randomsadness = random(0, 3);
    int randomsadnessrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::sadness[randomsadness]);
    delay(1000);
    answer(StoicResponses::sadnessrecom[randomsadnessrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(sad);
    idle = 0;
  }

  if (asr.isDetectCmdID(3))
  {
    k10.canvas->canvasClear();
    int randomstress = random(0, 3);
    int randomstressrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::stress[randomstress]);
    delay(1000);
    answer(StoicResponses::stressrecom[randomstressrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(think);
    idle = 0;
  }

  if (asr.isDetectCmdID(4))
  {
    k10.canvas->canvasClear();
    int randomafraid = random(0, 3);
    int randomafraidrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::afraid[randomafraid]);
    delay(1000);
    answer(StoicResponses::afraidrecom[randomafraidrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(think);
    idle = 0;
  }

  if (asr.isDetectCmdID(5))
  {
    k10.canvas->canvasClear();
    int randomangry = random(0, 3);
    int randomangryrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::angry[randomangry]);
    delay(1000);
    answer(StoicResponses::angryrecom[randomangryrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(sad);
    idle = 0;
  }

  if (asr.isDetectCmdID(6))
  {
    k10.canvas->canvasClear();
    int randomoverwhelmed = random(0, 3);
    int randomoverwhelmedrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::overwhelmed[randomoverwhelmed]);
    delay(1000);
    answer(StoicResponses::overwhelmedrecom[randomoverwhelmedrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(think);
    idle = 0;
  }

  if (asr.isDetectCmdID(7))
  {
    k10.canvas->canvasClear();
    int randommistake = random(0, 3);
    int randommistakerecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::mistake[randommistake]);
    delay(1000);
    answer(StoicResponses::mistakerecom[randommistakerecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(happy);
    idle = 0;
  }

  if (asr.isDetectCmdID(8))
  {
    k10.canvas->canvasClear();
    int randomnocontrol = random(0, 3);
    int randomnocontrolrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::nocontrol[randomnocontrol]);
    delay(1000);
    answer(StoicResponses::nocontrolrecom[randomnocontrolrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(think);
    idle = 0;
  }

  if (asr.isDetectCmdID(9))
  {
    k10.canvas->canvasClear();
    int randomunmotivated = random(0, 3);
    int randomunmotivatedrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::unmotivated[randomunmotivated]);
    delay(1000);
    answer(StoicResponses::unmotivatedrecom[randomunmotivatedrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(think);
    idle = 0;
  }

  if (asr.isDetectCmdID(10))
  {
    k10.canvas->canvasClear();
    int randomwisdom = random(0, 3);
    int randomwisdomrecom = random(0, 3);
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer(StoicResponses::wisdom[randomwisdom]);
    delay(1000);
    answer(StoicResponses::wisdomrecom[randomwisdomrecom]);
    delay(1000);
    answer("Is there anything else you want to talk about?");
    philosopher(happy);
    idle = 0;
  }

  if (asr.isDetectCmdID(11))
  {
    k10.canvas->canvasClear();
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    philosopher(think);
    answer("Thinking...");
    delay(1200);
    philosopher(talking);
    answer("Here is some music for you to relax. It's one of my favorites, please enjoy. If you want to talk to me again, please restart the device.");
    delay(1000);
    philosopher(happy);
    music.playTFCardAudio("S:/furelise.wav");
    idle = 0;
  }

  if (idle == 30)
  {
    k10.canvas->canvasClear();
    k10.canvas->canvasText("Stoic Buddy", 50, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 12, true);
    sleepingstate = true;
    philosopher(sleeping);
    answer("Zzz...");
  }
}

void showCommands()
{
  idle = 0;
  k10.canvas->canvasClear();
  k10.canvas->canvasText("Commands", 10, 30, 0x8A3F35, k10.canvas->eCNAndENFont24, 9, false);
  k10.canvas->canvasText("- I am happy -", 10, 60, 0x2F3145, k10.canvas->eCNAndENFont16, 15, false);
  k10.canvas->canvasText("- I am sad -", 10, 80, 0x2F3145, k10.canvas->eCNAndENFont16, 13, false);
  k10.canvas->canvasText("- I am stressed -", 10, 100, 0x2F3145, k10.canvas->eCNAndENFont16, 18, false);
  k10.canvas->canvasText("- I am afraid -", 10, 120, 0x2F3145, k10.canvas->eCNAndENFont16, 16, false);
  k10.canvas->canvasText("- I am angry -", 10, 140, 0x2F3145, k10.canvas->eCNAndENFont16, 15, false);
  k10.canvas->canvasText("- I am overwhelmed -", 10, 160, 0x2F3145, k10.canvas->eCNAndENFont16, 21, false);
  k10.canvas->canvasText("- I made a mistake -", 10, 180, 0x2F3145, k10.canvas->eCNAndENFont16, 21, false);
  k10.canvas->canvasText("- I cannot control -", 10, 200, 0x2F3145, k10.canvas->eCNAndENFont16, 21, false);
  k10.canvas->canvasText("- I feel unmotivated -", 10, 220, 0x2F3145, k10.canvas->eCNAndENFont16, 23, false);
  k10.canvas->canvasText("- Give me wisdom -", 10, 240, 0x2F3145, k10.canvas->eCNAndENFont16, 19, false);
  k10.canvas->canvasText("- Play music -", 10, 260, 0x2F3145, k10.canvas->eCNAndENFont16, 15, false);
  k10.canvas->updateCanvas();
}

void commands()
{
  asr.addASRCommand(1, "I am happy");
  asr.addASRCommand(2, "I am sad");
  asr.addASRCommand(3, "I am stressed");
  asr.addASRCommand(4, "I am afraid");
  asr.addASRCommand(5, "I am angry");
  asr.addASRCommand(6, "I am overwhelmed");
  asr.addASRCommand(7, "I made a mistake");
  asr.addASRCommand(8, "I cannot control");
  asr.addASRCommand(9, "I feel unmotivated");
  asr.addASRCommand(10, "Give me wisdom");
  asr.addASRCommand(11, "Play music");
}

void philosopher(String emotion)
{
  k10.canvas->canvasRectangle(50, 58, 150, 150, 0xebddab, 0xebddab, true);
  k10.canvas->canvasDrawImage(20, 50, emotion);
  k10.canvas->updateCanvas();
}

void answer(String msg)
{
  String firstline = "";
  String secondline = "";
  String thirdline = "";
  String fourthline = "";
  String fifthline = "";
  k10.canvas->canvasRectangle(10, 230, 220, 80, 0x8A3F35, 0xebddab, true);
  for (int i = 0; i < msg.length(); i++)
  {
    if (i < 32)
    {
      firstline += msg[i];
      k10.canvas->canvasText(firstline, 20, 235, 0x2F3145, Canvas::eCNAndENFont16, 34, false);
      k10.canvas->updateCanvas();
    }
    else if (i >= 32 && i < 64)
    {
      secondline += msg[i];
      k10.canvas->canvasText(secondline, 20, 248, 0x2F3145, Canvas::eCNAndENFont16, 34, false);
      k10.canvas->updateCanvas();
    }
    else if (i >= 64 && i < 96)
    {
      thirdline += msg[i];
      k10.canvas->canvasText(thirdline, 20, 261, 0x2F3145, Canvas::eCNAndENFont16, 34, false);
      k10.canvas->updateCanvas();
    }
    else if (i >= 96 && i < 128)
    {
      fourthline += msg[i];
      k10.canvas->canvasText(fourthline, 20, 274, 0x2F3145, Canvas::eCNAndENFont16, 34, false);
      k10.canvas->updateCanvas();
    }
    else if (i >= 128 && i < 160)
    {
      fifthline += msg[i];
      k10.canvas->canvasText(fifthline, 20, 287, 0x2F3145, Canvas::eCNAndENFont16, 34, false);
      k10.canvas->updateCanvas();
    }
  }
}

StoicResponses.h

Arduino
#ifndef STOICRESPONSES_H
#define STOICRESPONSES_H

#include <Arduino.h>

class StoicResponses
{
public:
    static const String greetings[];

    static const String happyness[];
    static const String happynessrecom[];

    static const String sadness[];
    static const String sadnessrecom[];

    static const String stress[];
    static const String stressrecom[];

    static const String afraid[];
    static const String afraidrecom[];

    static const String angry[];
    static const String angryrecom[];

    static const String overwhelmed[];
    static const String overwhelmedrecom[];

    static const String mistake[];
    static const String mistakerecom[];

    static const String nocontrol[];
    static const String nocontrolrecom[];

    static const String unmotivated[];
    static const String unmotivatedrecom[];

    static const String wisdom[];
    static const String wisdomrecom[];
};

#endif

StoicResponses.cpp

Arduino
#include "StoicResponses.h"

// Try to reach 130 char, not more than 160

const String StoicResponses::greetings[] = {
    "Hello friend. How was your day? How are you feeling? I'm always here to support you and help you navigate both the good moments and the difficult ones.", 
    "How are you doing today, friend? Is there something special you'd like to talk about today? Or would you like to listen to some relaxing music?", 
    "I was just thinking about you. Welcome back, my friend. What's on your mind today? Is something bothering you? How was your day?"
};

const String StoicResponses::happyness[] = {
    "You seem happy! Today was a good day. I can see you're full of energy and eager to do many things. Channel all those emotions into something great.",
    "There's nothing better than having a good day. Just remember that life is full of ups and downs, so take a moment to enjoy and appreciate these moments.",
    "Amazing! We both know that life can be hard, and these happy days are what help carry us through. Cherish them, and share that happiness with people you love."

};

const String StoicResponses::happynessrecom[] = {
    "Let's do some exercise! Use that great energy to burn some calories and take care of your health. And don't forget to drink some water on your way out!",
    "I recommend going out and spending some time in nature. Even if you live in a city, try to find a park or spend some time near the ocean. Take a moment to chill",
    "Let's share this amazing news with someone close to you. Believe me, happiness and kindness are contagious—they'll feel just as happy as you do right now."
};

const String StoicResponses::sadness[] = {
    "That's unfortunate. Life can be rough sometimes, but those challenges can make us stronger when we overcome them. Tomorrow will be a better day—trust me.",
    "Just as the famous Epictetus said: “Remember that it is not events that disturb people, but their judgments about them.” Take a moment to breathe and reflect.",
    "Do not suffer before the crisis arrives. Many things trouble us more than they should, before they should, or even when they should not trouble us at all."
};

const String StoicResponses::sadnessrecom[] = {
    "I know it may be difficult, but let's try something. Let's work out today—go for a walk or lift some weights. Scientifically, you'll almost certainly feel better afterward.",
    "Music is the solution to many things, and having a bad day go to a good one is one of them, play your favorite beat up playlist and think about the good memories.",
    "Text your loved ones—family or close friends—and share how your day went. I'm sure they'll listen and offer support or advice. Go out with them!",
};

const String StoicResponses::stress[] = {
    "Remember that you have power over your mind, not outside events. Realize this and you will find strength.",
    "It is important to understand that anything outside your control cannot be controlled. What you can control is how you think about it.",
    "Stress often comes from our thoughts. We usually suffer more in our imagination than in reality."
};

const String StoicResponses::stressrecom[] = {
    "Promise me you will take a few minutes to rest your mind. Stay away from social media for a while, grab a coffee, and read some literature.",
    "Try some deep breathing: inhale for 4 seconds, hold for 7, and exhale for 8. This helps calm the nervous system and reduce stress.",
    "Take a walk and stretch your legs. This helps release tension and endorphins while you listen to some relaxing music."
};

const String StoicResponses::afraid[] = {
    "It's okay to be afraid. It makes us human, and it is a natural survival instinct. Sometimes the best thing we can do is conquer our fears step by step.",
    "Remember that you gain strength, courage, and confidence every time you overcome a fear. Treat this as a challenge and face it.",
    "I understand how you feel. Fear is a powerful emotion, but remember to never let fear control you."
};

const String StoicResponses::afraidrecom[] = {
    "If you want to overcome this fear, create a small hierarchy of challenges. Start with the easiest one and slowly work your way up.",
    "Try not to avoid your fear. Sometimes it is important to safely confront it so you can learn to cope and realize it may not be as scary as it seems.",
    "Speak positively to yourself every day. Visualize yourself in a difficult situation and imagine handling it calmly."
};

const String StoicResponses::angry[] = {
    "Never let your emotions get the best of you. Delay this feeling as much as you can and give yourself time to think things through.",
    "Seek perspective. Imagine this event happening to someone else and try to feel sympathy rather than rage.",
    "Inner control is important. Do not let anger control your actions or your thinking. We are often disturbed by our own view of things."
};

const String StoicResponses::angryrecom[] = {
    "Take a timeout. Remove yourself from the situation, step outside your room, take a walk, and get some fresh air.",
    "Channel this energy into an intense workout like running, jogging, walking, or lifting weights. Even squeezing a stress ball can help.",
    "Take slow, deep breaths and listen to some of your favorite music. This can help improve your mood and calm your mind."
};

const String StoicResponses::overwhelmed[] = {
    "I know the feeling. Everything seems to be piling up, and you don't know what to do. Let's pause for a moment and simply be in the present.",
    "It's completely normal to feel overwhelmed. This often happens because of overthinking and having many tasks at once. Keep the following in mind:",
    "Humans tend to have limits, even when thinking. It's important to keep this in mind when feeling overwhelmed. You need to pause what you're doing for a minute"
};

const String StoicResponses::overwhelmedrecom[] = {
    "Divide your worries into what you can control (your thoughts, actions, and responses) and what you cannot (other people, outcomes, and the past). Discard the latter.",
    "Instead of being paralyzed and doing nothing, focus on the absolute smallest step you can take right now. Start there and build up toward your final task.",
    "When you feel overwhelmed, pause to regain composure rather than acting impulsively. Listen to some calm music, go for a walk, and leave your smartphone at home."
};

const String StoicResponses::mistake[] = {
    "Let me tell you something: mistakes don't define who you are. What matters is getting up and fixing them with the best attitude possible. Believe this, and you'll be okay.",
    "You must take responsibility for the actions you take. Even if you make a mistake, what matters is that you learn from it so you don't repeat it again.",
    "Mistakes are part of the healthy lifestyle of someone who is trying. You'll gain wisdom by learning from them and grow into a better human being."
};

const String StoicResponses::mistakerecom[] = {
    "Let's analyze the cause of your mistake, its root, and how the impact affects you or your environment. With this information, you can work toward a solution.",
    "Sometimes it's good to seek feedback from a close friend or a colleague. Perspectives outside your own are valuable when analyzing a situation."
    "Avoid self-blame and be compassionate with yourself. Don't treat yourself too harshly, everyone makes mistakes, and you will learn from them."
};

const String StoicResponses::nocontrol[] = {
    "It's important to know what we have control over and what we don't. You can control your emotions, actions, and thoughts, anything else is external.",
    "Don't let external sources dictate your life. What happens outside your control should not affect your emotions. Even though it's difficult, once you realize this, you can gain control over your mind.",
    "A Stoic acts like an archer: they train, take aim, and shoot with maximum skill, but accept that a sudden gust of wind (external factors) may cause them to miss the target."
};

const String StoicResponses::nocontrolrecom[] = {
    "Let's practice this: grab a notebook and write all the things you have control over on one side, and the things you don't have control over on the other side.",
    "Walk out your emotions, sometimes we think we have control over external things, but we have to let these actions pass through and don't let us affect our life.",
    "Practice some deep breathing techniques to let those unwanted thoughts pass. Many things we cannot control try to affect us, so stop what you're doing and take a moment to practice some breathing techniques"
};

const String StoicResponses::unmotivated[] = {
    "Life is full of ups and downs, and days when we feel unmotivated are completely normal. It is important to keep our discipline strong.",
    "We should not depend on motivation to push ourselves to do things. Discipline is what makes us do the things we sometimes feel we don't want to do.",
    "Feeling like this is normal. However, you should get up and try once again. You can rest and take a few minutes to think, but once you're done, you must push through."
};

const String StoicResponses::unmotivatedrecom[] = {
    "Make sure you rest today. Keep this day free from work and think about what to do in these scenarios, so that the next time you feel like this again, you can use your discipline in your favor.",
    "Write down your why, connect with your deeper purpose or values, which helps sustain motivation even when tasks are challenging.",
    "Let's make a routine, grab a notebook and try to build consistency to turn actions into habits, reducing the need for constant motivation."
};

const String StoicResponses::wisdom[] = {
    "If you want to be happy, do not desire that things happen as you wish, but wish that they happen as they do. - Epictetus",
    "Life is very short and anxious for those who forget the past, neglect the present, and fear the future. - Seneca",
    "You have power over your mind, not outside events. Realize this, and you will find strength. - Marcus Aurelius"
};

const String StoicResponses::wisdomrecom[] = {
    "If you wish to find more motivation, i recommend you to read the following book: Meditations by Marcus Aurelius.",
    "If you wish to find more motivation, i recommend you to read the following book: Letters from a Stoic by Seneca.",
    "If you wish to find more motivation, i recommend you to read the following book: Discourses, Fragments, Handbook by Epictetus."
};

The Stoic Buddy

Credits

Jorge Eldis González
2 projects • 0 followers
Electrical and Electronic Engineer. I work as a Software Developer, specializing in full-stack web applications & embedded systems.

Comments