Massive site refactoring
All checks were successful
Build and Publish Docker Image / build (push) Successful in 3m32s
All checks were successful
Build and Publish Docker Image / build (push) Successful in 3m32s
This commit is contained in:
4
content/blog/_index.md
Normal file
4
content/blog/_index.md
Normal file
@@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Blog"
|
||||
summary = "Tutorials, guides, and technical ramblings from a dragon."
|
||||
+++
|
||||
BIN
content/blog/dnd-monsters/featured.jpg
Normal file
BIN
content/blog/dnd-monsters/featured.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 MiB |
107
content/blog/dnd-monsters/index.md
Normal file
107
content/blog/dnd-monsters/index.md
Normal file
@@ -0,0 +1,107 @@
|
||||
+++
|
||||
date = '2026-05-26T16:00:00-06:00'
|
||||
draft = false
|
||||
title = "How a dragon runs his monsters"
|
||||
summary = "Learn how to make impromptu monsters in Dnd, as well as how to run a homebrew monster."
|
||||
tags = ['ttrpg', 'tutorial', 'dnd']
|
||||
+++
|
||||
|
||||
## How to make a punching bag
|
||||
|
||||
{{< typeit
|
||||
tag=h3
|
||||
speed=50
|
||||
breakLines=false
|
||||
>}}
|
||||
"Can I roll to attack the barrel?" — Random player
|
||||
{{< /typeit >}}
|
||||
|
||||
How does a dragon run **DnD?** Have you ever wondered how to build and come up with creatures on the fly?
|
||||
|
||||
I'll outline some of my tips and tricks below on how I run completely random encounters based on the situation and players.
|
||||
|
||||
## Coming up with a monster
|
||||
|
||||
There are lots of beasties available via the **Monster Manual** and a pleathora of other sources including homebrew and third party monsters. **So why bother?**
|
||||
|
||||
**I'm an insane person.**
|
||||
|
||||
Anyways, I always like the personal touch of bringing creatures players have not seen before. Meta-gamer's cant take advantage of their *out-of-character* knowledge about monster stats, and players get a unique experience. That still leaves the question, **how do you make a monster?**
|
||||
|
||||
### Read the situation
|
||||
|
||||
One of the main keys is to **read the situation**, literally. If players are in a tavern, what kind of things could they end up fighting in a tavern? How about in a forest? It doesn't have to be something crazy, nor does it not have to be something crazy. Some monsters I make up I really let go wild.
|
||||
|
||||
For example, one such monster was a fungus monster that had one attack, eat. The players were in a forest with a bunch of mushrooms, Ureka!, let's have them fight a fungus.
|
||||
|
||||
I also like to take inspiration from media and even existing monsters, watching too much **Gravity Falls**? Add some chaotic demon for the players to fight. Need an interesting city showdown? Why not pull in a sharp shootin outsider wearing all black.
|
||||
|
||||
Of course, keep in mind whether you care about **consistency in your world**. Some things make less sense than others. But let your creativity soar.
|
||||
|
||||
## Running a homebrew monster
|
||||
|
||||
One of the tricks to homebrew monsters is how I run combat. I find combat, in **DnD** specifically, quite tedious; so doin the least amount of math and rolling works out best for me.
|
||||
|
||||
### Gauging difficulty
|
||||
|
||||
There are a few ways to quickly gauge a monster's difficulty.
|
||||
|
||||
- **The Monster's AC,** *how hard they are to hurt*
|
||||
- **The Monster's Attacks,** *how hard they hit back*
|
||||
- **The Monster's HP,** *how long they can fight*
|
||||
- **The Amount of Monsters,** *how overwhelmed players will feel*
|
||||
|
||||
The first thing I usually decide is how hard do I want this fight.
|
||||
|
||||
This unfortunately usually takes a little feel for the game. I start by figuring out how I want to direct combat. Some key things to keep in mind for directing combat would be, **Is this a Boss fight? Are the players going to be fighting a large group of enemies or just one?** How you construct your encounter will greatly impact how you have to manage monster difficulty.
|
||||
|
||||
For instance, if you want to run a **Boss Battle**, you need to consider some key things: if there are lots of players, you will want to give your monster some **[Legendary Actions](https://arcaneeye.com/mechanic-overview/legendary-actions-5e/)** or give them some **Minions**. You will also need to consider how tough the boss is or how powerful are its attacks?
|
||||
|
||||
If instead you want a scuffle in the woods with bandits, consider the amount of bandits and how hard they should be to kill, **which leads me to my next trick...**
|
||||
|
||||
### Deciding the AC and the HP
|
||||
|
||||
**Armor Class** is essential to certain combats, it makes a difficult monster truly difficult. But I also try to make sure it makes sense, if a **Monster is a big fleshy beast** the size of a barn, it probably **will not have that great of an AC**.
|
||||
|
||||
Conversely, **Health Points** are the yin to the yang of **AC**. They truely make the fight either shorter or longer. Every monster stat block will have the **Dice roll** for **HP** such as `2d8+20 (29)` which is helpful in drafting up random health. I personally don't like that approach and instead I usually measure a fight in a **"How many times can this enemy be hit?"** approach.
|
||||
|
||||
If it is a weak enemy like an enemy raider, perhaps he will have an **AC of `14`** with his default armor, and perhaps **he can take about 2 hits**.
|
||||
|
||||
I usually only track HP for enemies as a show for players, sometimes I actually roll out the **HP**, but it honestly takes gauging the feel. Sometimes it is necessary, like for a boss, other times it is unnecessary, for instance a swarm of bats.
|
||||
|
||||
### How much damage should my monster do?
|
||||
|
||||
Do NOT go nuts with damage. If your average **player has `30` HP**, your monster's attacks generally should not do **more than `60-80%`** of the average player's health. We generally want to have a fun and engaging fight, not to **[TPK](https://blackcitadelrpg.com/dnd-acronym-list/)** the party.
|
||||
|
||||
For instance, I like to scale my damage off of existing weapons, or using a [dice calculator](https://dice.clockworkmod.com).
|
||||
|
||||
| Device | Damage Dice | Average Damage |
|
||||
|------------|--------------|----------------|
|
||||
| Flail | `1d8 + mod` | `4.5 + mod` |
|
||||
| Glaive | `1d10 + mod` | `5.5 + mod` |
|
||||
| Greataxe | `1d12 + mod` | `6.5 + mod` |
|
||||
| Greatsword | `2d6 + mod` | `7 + mod` |
|
||||
|
||||
I also use existing monster features a lot, if your monster only does an average of `8` damage a hit, but you need twice that, have your monster get **Multiattack** for instance on the [brown bear statblock](https://www.dndbeyond.com/monsters/16816-brown-bear).
|
||||
|
||||
Back to my previous example with the **Giant Fungus** the attack and method for which players can escape was heavily inspired by the **[purple worm](https://www.dndbeyond.com/monsters/16987-purple-worm)**, I however nerfed a few requirements, dropping the `30` to `16`, and the damage to `3d6`.
|
||||
|
||||
### The tiresome fight
|
||||
|
||||
The final thing I try to avoid, is a **tiresome fight**.
|
||||
|
||||
What I mean by that is **when combat gets too drawn out, it needs to end**. A thrilling combat should not devolve into **play fighting with foam swords**.
|
||||
|
||||
If your enemy is **not doing enough damage**, perhaps he had some **friends lurking nearby**. If the enemy is too hard to fight, perhaps **every hit now counts for two hits or double damage**.
|
||||
|
||||
## Why do we do what we do
|
||||
|
||||
**We do it for the players.**
|
||||
|
||||
While it is fun to dream up horrific monsters that players have to fight and have no chance winning against, we want everyone to have fun. **Your monsters should be a challenge**, but they should not be a death sentence.
|
||||
|
||||
We want to tell a story and we want to give the players something memorable that keeps bringing them back.
|
||||
|
||||
Of course, this is not the only way to create your own monsters, heck, you don't even need to run combat the way I do, my hope is that perhaps my words will inspire your future games.
|
||||
|
||||
Happy rolling!
|
||||
BIN
content/blog/how-to-dm-1/board.jpg
Normal file
BIN
content/blog/how-to-dm-1/board.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
content/blog/how-to-dm-1/books.jpg
Normal file
BIN
content/blog/how-to-dm-1/books.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 731 KiB |
BIN
content/blog/how-to-dm-1/dice.jpg
Normal file
BIN
content/blog/how-to-dm-1/dice.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 MiB |
BIN
content/blog/how-to-dm-1/featured.jpg
Normal file
BIN
content/blog/how-to-dm-1/featured.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 MiB |
94
content/blog/how-to-dm-1/index.md
Normal file
94
content/blog/how-to-dm-1/index.md
Normal file
@@ -0,0 +1,94 @@
|
||||
+++
|
||||
date = '2026-05-24T16:00:00-06:00'
|
||||
draft = false
|
||||
title = "So you wanna GM?"
|
||||
summary = "Have you ever wanted to be a GM? Learn some of the tips and tricks that help me run games as a Game Master."
|
||||
tags = ['ttrpg', 'tutorial']
|
||||
+++
|
||||
|
||||
## Being the Game Master
|
||||
|
||||
One of the biggest problems I face when playing **TTRPG**, is the disparity of people that want to play **TTRPGs** and the lack of people who sign up to be **GMs**.
|
||||
When I ask people if they want to be a **GM**, they often express fears of screwing up at running or not being able to run a game due to all the things
|
||||
a **GM** has to track.
|
||||
|
||||
I firmly believe that anyone can be a **GM** due to endless resources and tools available, allowing anyone to **GM** regardless of experience or physical resources.
|
||||
In this post I'm going to go over my revelations as a GM over the past few years and hopefully share some tips and tricks that came in handy for me.
|
||||
|
||||
## What's a GM need?
|
||||
|
||||

|
||||
|
||||
What does a **GM** need to start running a **TTRPG**? All the books? A table to play on? What I usually find the main thing you need is players. I own a lot of books and they are a costly investment. A new player might be tempted to run and grab the **Dungeon Master's Handbook** from **Wizards of the Coast**, or any similar reading material for the game you are looking to play.
|
||||
|
||||
While this is a usefull source of information, it is still plagued by some rather annoying issues, mainly that it is a book. You will also find that a lot of the information necessary to run a game is already available to you for free in the form of Wiki pages and self published information by the corresponding company. For instance, if you need the stat block of a monster from **DnD** you can simply google it, such as: **"DnD Lich"** which gave me [this Roll20 page](https://roll20.net/compendium/dnd5e/Lich#content)
|
||||
|
||||
### Minimalism is enough
|
||||
|
||||
> "Don't I need a bunch of maps, minis and such?"
|
||||
|
||||
My usual toolkit is quite simple. When I am running games I usually bring a **blank dry-erase map**, a bag full of **flat marbles** and a couple **map books**. In many ways this kit itself is also overkill, I have played games where all the **GM** had was a standard school journal, a pencil and some pieces from a board game. This leads me to my first main point.
|
||||
|
||||
What really matters most is people; can't have a cooperative RPG without players (usually).
|
||||
|
||||
When I first started running games I started with a pair of friends which gave us a dinner table with 3 folks to play games.
|
||||
You will find that when you start to run **DnD**, some clearly distinct types of players will show up. There are those that love to **role-play** and are super invested in story, there are those that love the crunchy number heavy aspects of games.
|
||||
|
||||
### Matching playstyles
|
||||
|
||||
My biggest failing as a **GM** is trying to please everyone, some playstyles dont jive well. If you are interested in running a **full campaign**, I recommend first starting with a couple **one-shots** to acclimate and in some ways "interview" players for a role. **One-shots** work well because they are zero stake adventures that can take anywhere from an hour to three. Ultimately, the goal of a **TTRPG** is to tell a story, in many ways games like **DnD**, **Pathfinder**, etc are cooperative storytelling games. This is why it is important to find players that play well together.
|
||||
|
||||
## How do I tell a story?
|
||||
|
||||

|
||||
|
||||
Storytelling may not come easily to some, in many aspects getting good at **TTRPG** games will require some learning regarding improv. My recommendation for someone who has never run a **TTRPG** game before is to first try a guided **one-shot**. A classic **one-shot** that I have run in the past is [The Wolves of Welton](https://winghornpress.com/adventures/wolves-of-welton/), which is a short low level **one-shot** about magic talking wolves. My personal strategy to telling a compelling story is to allow the act of cooperative storytelling and improv to guide me to a conclusion.
|
||||
|
||||
### Example of my process
|
||||
|
||||
An example of my process for telling a story is I first come up with an interesting hook. It is important to start campaigns and one-shots with hooks, some reason for the party to do what they are doing. If it is a **one-shot** it is a lot more flexible since you can easily say for example: *"You are a traveling group, and you are desperate for food, thankfully there is a kindly monk up ahead in the road selling food."*.
|
||||
This sets the stage for your group of players to first, act like a group. We also set the expectations of the group, their immediate problem is their players are starving, this quickly gives their character motivation.
|
||||
|
||||
### The bread-crumb trail
|
||||
|
||||
You then start to create a **bread crumb trail**, we offer this in the form of a friendly monk who has food for sale. This is an essential start to any game, you need to give players the who, the what, and the why, exactly as you would in a story. This is ever more important when running a campaign as you need to provide a hook that sets up the entire campaign, for this reason, I heavily recommend if you want to get started running **TTRPG** campaigns, use a prebuilt one as it will handle the story telling aspects of the who, what and why.
|
||||
|
||||
## Game master toolkit
|
||||
|
||||

|
||||
|
||||
There are some key cheats that every **GM** can take advantage of when running a game. Consider them part of your standard **GM** tookit.
|
||||
|
||||
### When to roll
|
||||
|
||||
You should only ever make players roll for something when there is a possibility of a **meaningful failure**. For example, if a player wants to pick open a door, can they fail in a meaningful way? Such as, their picks break, they alert a guard, etc? Then have a roll. Do not make players roll to do mundane tasks that they can eventually succeed at without consequence.
|
||||
|
||||
Dice rolls should never be **tedious**, we want them to help shape and tell a story, **not inconvenience players**.
|
||||
|
||||
### Success is temporary, faliure is forever
|
||||
|
||||
As much fun as it is for players to always succeed, the most memorable moments are when things went horribly wrong. Don't go out of your way to actively punish players, but encourage risk, play the devils advocate.
|
||||
|
||||
This will reward the cooperative story telling and push the plot along creating memorable journeys for you and your players.
|
||||
|
||||
### Carrot and a stick
|
||||
|
||||
Sometimes it is impossible to avoid **railroading** your players, which is when you force your players to play a game that is on the tracks.
|
||||
|
||||
I try to push players in the right direction using the **Carrot and Stick** method. If you need players to go somewhere, don't take away their agency, instead lure them there with a very juicy **Carrot**.
|
||||
|
||||
For example, if you need players to go to a specific place, secretly **plant a seed**, perhaps something precious is secretly stolen from the players. When they go to look for their precious item, the instead find a note detailing where they can go to pay a ransom.
|
||||
|
||||
### Cooperative story telling
|
||||
|
||||
A lot of **GM's** see **TTRPGs** as a **player vs GM** situation, and while many **TTRPGs** may focus on that in some aspect, I think its more important to be a **storytelling platform**.
|
||||
|
||||
The attitude that you are actively against the players hinders the cooperative atmosphere that gives players the chance to explore and come up with ideas. I try to focus less on how I can screw over my players, and more how I can challenge them and build an enjoyable story for everyone.
|
||||
|
||||
You are not the sole storyteller, the players are there to help. If you give players enough agency, they will actively tell the story with you, it is ultimately just your job to coordinate and make sure the story makes sense.
|
||||
|
||||
## Jump in headfirst
|
||||
|
||||
Ultimately the best way to learn to **GM** is to do. Find a couple friends, grab a couple pieces of paper, do some reading and start a game.
|
||||
|
||||
You can spend forever planning and trying to get every aspect ready, but what really pays off is just playing the game. Players are there to support you, and help you tell the story.
|
||||
BIN
content/blog/katchi/featured.jpg
Normal file
BIN
content/blog/katchi/featured.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 MiB |
322
content/blog/katchi/index.md
Normal file
322
content/blog/katchi/index.md
Normal file
@@ -0,0 +1,322 @@
|
||||
+++
|
||||
date = '2026-05-17T23:57:15-06:00'
|
||||
draft = false
|
||||
title = "Katchi, a dragon's best friend"
|
||||
summary = "Buidling a smart speaker with ESPHome for Home Assistant, and it just so happens to look like a kobold."
|
||||
tags = ['kobold', 'esp32']
|
||||
+++
|
||||
|
||||
## A smart-home for a Dragon
|
||||
|
||||
{{< typeit
|
||||
tag=h3
|
||||
speed=50
|
||||
breakLines=false
|
||||
loop=true
|
||||
>}}
|
||||
"It's the Future..."
|
||||
"Dumb homes are so 2010"
|
||||
"Is all of this really necessary?" — Concerned Friends
|
||||
{{< /typeit >}}
|
||||
|
||||
### Smart-homes
|
||||
|
||||
The present state of smart-home choices is fairly acceptable. You have your major players, **Google**, **Apple**, **Amazon** and
|
||||
their associated services like Google Home or **Alexa**. These systems are fairly easy to set up; plug in the new device,
|
||||
type in some credentials or type a prompt on your phone, and done. Most of these systems rely on a central hub that
|
||||
orchestrates the entire smart home.
|
||||
|
||||
But all these systems have one fatal annoyance. They all require access to the internet.
|
||||
|
||||
### Internet dependency
|
||||
|
||||
In recent years, it is common to run into issues with major providers. Privacy concerns, outages and the forced
|
||||
obsolescence of existing systems put a lot of pressure on me when building my first smart home. Sure the big players
|
||||
make it easy to set up and use, but for me the non-monetary cost was just too great. Besides the limitations in software,
|
||||
knowing that if I had an internet outage, or god forbid, the provider has an outage, I would be shit out of luck in
|
||||
turning off my lights turned me away from major providers.
|
||||
|
||||
### So what did I use?
|
||||
|
||||
After spending a lot of time frustrated with my options and dealing with the difficulties in automating and doing what
|
||||
I wanted with my smart-home, I went down the rabbit hole of options and found
|
||||
**[Home Assistant](https://www.home-assistant.io/)**.
|
||||

|
||||
|
||||
Unlike the big-name smart-homes, **Home Assistant** is a self-hosted option that runs on your own hardware and locally
|
||||
connects to supported devices. It supports a wide range of [devices and integrations](https://www.home-assistant.io/integrations/?brands=featured)
|
||||
and is fairly easy to set up.
|
||||
|
||||
I wont expound on it much more here, but I will link to the [getting started](https://www.home-assistant.io/installation/), [documentation](https://www.home-assistant.io/docs/)
|
||||
and [community](https://community.home-assistant.io/) for more information.
|
||||
|
||||
### So what's the problem?
|
||||
|
||||
Of all the amazing options that **Home Assistant** gives us, it has a fairly significant miss; that being Smart Speaker integration.
|
||||
|
||||
## Home Assistant Smart Speaker
|
||||
|
||||
The options for **Home Assistant** smart speakers are quite limited, they only offer one official product as of the date of publishing this post.
|
||||
|
||||
{{< externalLink url="https://www.home-assistant.io/voice-pe/" >}}
|
||||
|
||||
While the **Home Assistant Voice PE** works decently, it is the only off-the-shelf option for **Home Assistant** which considering
|
||||
all the freedom **Home Assistant** gives us, feels quite limiting. However, there is a solution.
|
||||
|
||||
### The Solution
|
||||
|
||||
Thankfully we are not constrained by the limitations of existing hardware thanks to microcontrollers, specifically the ESP family of microcontrollers.
|
||||

|
||||
|
||||
Using **[ESPHome](https://esphome.io)** you can create a whole myriad of smart devices based on the [ESP32 microcontroller](https://www.espressif.com/en/products/socs/esp32). It provides a very diverse
|
||||
family of options that can fit nearly any use-case. Think of it as an alternative to Arduino, where instead of writing C code
|
||||
you can write yaml configuration files that dictate and configure your ESP device.
|
||||
|
||||
Knowing this, I set out to make my own Smart Speaker.
|
||||
|
||||
## Building a Katchi (smart speaker)
|
||||
|
||||
So what does it take to make a smart speaker? You ultimately need a few key things such as a Speaker, a Microphone and a
|
||||
Wifi-enabled Microcontroller. For my purposes I decided I also wanted a screen so I could give my Katchi a little
|
||||
more personality. The main requirement I had for the display was for it to be circular as my intent was to use the display
|
||||
as the eye for my smart speaker.
|
||||
|
||||
### Waveshare ESP32-S3
|
||||
|
||||
I ended up landing on the [Waveshare ESP32-S3 1.75inch AMOLED Round Touch Display Development Board](https://www.waveshare.com/esp32-s3-touch-amoled-1.75.htm).
|
||||
Despite being quite a mouthful, this handy little device is absolutely packed with sensors and features, as well as a
|
||||
glorious AMOLED round display.
|
||||
|
||||
{{< gallery >}}
|
||||
{{< figure src="https://www.waveshare.com/media/catalog/product/cache/1/image/800x800/9df78eab33525d08d6e5fb8d27136e95/e/s/esp32-s3-touch-amoled-1.75-1.jpg" alt="Gallery image 1" figureClass="grid-w33" >}}
|
||||
{{< figure src="https://www.waveshare.com/media/catalog/product/cache/1/image/800x800/9df78eab33525d08d6e5fb8d27136e95/e/s/esp32-s3-touch-amoled-1.75-2.jpg" alt="Gallery image 2" figureClass="grid-w33" >}}
|
||||
{{< figure src="https://www.waveshare.com/media/catalog/product/cache/1/image/800x800/9df78eab33525d08d6e5fb8d27136e95/e/s/esp32-s3-touch-amoled-1.75-3.jpg" alt="Gallery image 3" figureClass="grid-w33" >}}
|
||||
{{< /gallery >}}
|
||||
|
||||
Some of the fundamental things to take note of when considering esp devices, is what components and associated drivers
|
||||
are available in **ESPHome**. For the Waveshare device I picked, it has the following components and their support:
|
||||
|
||||
| Device | Purpose | Supported |
|
||||
|---------|-----------------------------------------|--------------------------------------------------------|
|
||||
| TCA9554 | GPIO expander for additional interfaces | [Yes](https://esphome.io/components/pca9554/) |
|
||||
| ES7210 | ADC for microphones | [Yes](https://esphome.io/components/audio_adc/es7210/) |
|
||||
| ES8311 | DAC for speaker | [Yes](https://esphome.io/components/audio_dac/es8311/) |
|
||||
| CO5300 | Display controller for amoled | [Yes](https://esphome.io/components/display/mipi_spi/) |
|
||||
| CST9217 | Touchscreen control device | No |
|
||||
|
||||
To fill in the support gap for the touch screen, we can make use of an [external driver](https://github.com/shelson/esphome-cst9217) to handle making the touchscreen
|
||||
work.
|
||||
|
||||
### Configuration
|
||||
|
||||
Since **ESPHome** uses a yaml configuration file to define the device, configuring the device is fairly straightforward.
|
||||
|
||||
#### Basic Configuration
|
||||
|
||||
We first need to start with the basic confguration of the device. When setting up the esp32 configuration, it is crucial
|
||||
to be aware of the Flash size and CPU frequency otherwise your device may not run correctly. For the device I am using,
|
||||
it has a **16MB flash** and a **240MHz CPU**. We also use the esp-idf framework. This is the preferred framework for
|
||||
esp devices as the Arduino framework is not as feature-rich and is no longer supported by newer devices.
|
||||
|
||||
```yaml
|
||||
esphome:
|
||||
name: kobold
|
||||
friendly_name: Kobold
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
flash_size: 16MB
|
||||
cpu_frequency: 240MHZ
|
||||
framework:
|
||||
type: esp-idf
|
||||
```
|
||||
|
||||
We also need to set up **psram**, the **i2c bus** as well as the **SPI bus**. This will require
|
||||
a firm understanding of the GPIO pins and their associated functions. For the Waveshare device,
|
||||
they provide the following pinout diagram: [ESP32-S3-Touch-AMOLED-1.75.pdf](https://files.waveshare.com/wiki/ESP32-S3-Touch-AMOLED-1.75/ESP32-S3-Touch-AMOLED-1.75.pdf)
|
||||
We will rely on this document extensively for the rest of the configuration.
|
||||
|
||||
The **psram** is important for making sure that the device does not run out of memory.
|
||||
and its config is quite simple.
|
||||
|
||||
```yaml
|
||||
psram:
|
||||
mode: octal
|
||||
speed: 80MHz
|
||||
```
|
||||
|
||||
The **i2c bus** is used for the touchscreen and for other future components and acts as
|
||||
an important communication protocol for Microcontrollers as it allows a large amount of
|
||||
sensors and devices to connect to the same bus.
|
||||
|
||||
```yaml
|
||||
i2c:
|
||||
sda: GPIO15
|
||||
scl: GPIO14
|
||||
scan: true
|
||||
id: bus_a
|
||||
```
|
||||
|
||||
The **SPI bus** is essential for the display module as it communicates via quad SPI which is functionally
|
||||
a quad channel serial bus.
|
||||
|
||||
```yaml
|
||||
spi:
|
||||
- id: spi_bus
|
||||
clk_pin: GPIO2
|
||||
mosi_pin: GPIO1
|
||||
miso_pin:
|
||||
number: GPIO3
|
||||
ignore_strapping_warning: true
|
||||
- id: quad_spi_bus
|
||||
type: quad
|
||||
clk_pin: GPIO38
|
||||
data_pins:
|
||||
- GPIO4
|
||||
- GPIO5
|
||||
- GPIO6
|
||||
- GPIO7
|
||||
```
|
||||
|
||||
#### Display Configuration
|
||||
|
||||
For our basic display configuration we will use the **mipi_spi** display driver. This driver
|
||||
specifically requires the **quad SPI bus** to be configured as well as the correct `data_rate`.
|
||||
You can play with the data rate for a **quad SPI display** as it will impact how the display refreshes and draws images.
|
||||
```yaml
|
||||
display:
|
||||
- platform: mipi_spi
|
||||
id: disp1
|
||||
model: CO5300
|
||||
bus_mode: quad
|
||||
reset_pin: GPIO39
|
||||
cs_pin: GPIO12
|
||||
data_rate: 80MHz
|
||||
dimensions:
|
||||
height: 466
|
||||
width: 466
|
||||
offset_width: 6
|
||||
```
|
||||
|
||||
#### Audio Configuration
|
||||
|
||||
Our audio configuration is quite a bit more complex. It requires we configure its own **SPI bus** as well as the **DAC**
|
||||
and **ADC** configs. Finally we then need to actually configure the audio components.
|
||||
|
||||
Our **audio SPI bus** is more simple than our **quad SPI bus**
|
||||
|
||||
> we ignore the strapping pin here to prevent warnings being thrown. Read more about this [here](https://esphome.io/guides/configuration-types/#pin-schema)
|
||||
|
||||
```yaml
|
||||
i2s_audio:
|
||||
- id: i2s_audio_bus
|
||||
i2s_mclk_pin: GPIO42
|
||||
i2s_bclk_pin: GPIO9
|
||||
i2s_lrclk_pin:
|
||||
number: GPIO45
|
||||
ignore_strapping_warning: true
|
||||
```
|
||||
|
||||
We then need to configure both our **DAC** and **ADC** drivers. For the ease of syncing our configs and not confusing changes
|
||||
in the future, we will first add substitutions.
|
||||
|
||||
```yaml
|
||||
substitutions:
|
||||
i2s_bps_spk: 16bit
|
||||
i2s_bps_mic: 16bit
|
||||
i2s_sample_rate_spk: 44100
|
||||
i2s_sample_rate_mic: 16000
|
||||
```
|
||||
|
||||
We can then configure our **ADC** and **DAC** drivers and make use of these substitutions.
|
||||
|
||||
```yaml
|
||||
audio_adc:
|
||||
- platform: es7210
|
||||
id: es7210_adc
|
||||
bits_per_sample: $i2s_bps_mic
|
||||
sample_rate: $i2s_sample_rate_mic
|
||||
|
||||
audio_dac:
|
||||
- platform: es8311
|
||||
id: es8311_dac
|
||||
bits_per_sample: $i2s_bps_spk
|
||||
sample_rate: $i2s_sample_rate_spk
|
||||
```
|
||||
|
||||
Once we have our audio drivers configured, we can configure our **audio output** and **audio input** devices. We configure
|
||||
our audio devices using the same substitutions allowing us to change sample rates and bit depths without a possible
|
||||
mismatch between driver and device.
|
||||
|
||||
```yaml
|
||||
microphone:
|
||||
- platform: i2s_audio
|
||||
id: box_mic
|
||||
sample_rate: $i2s_sample_rate_mic
|
||||
i2s_din_pin: GPIO10
|
||||
bits_per_sample: $i2s_bps_mic
|
||||
adc_type: external
|
||||
|
||||
speaker:
|
||||
- platform: i2s_audio
|
||||
id: box_speaker
|
||||
i2s_dout_pin: GPIO8
|
||||
dac_type: external
|
||||
sample_rate: $i2s_sample_rate_spk
|
||||
bits_per_sample: $i2s_bps_spk
|
||||
audio_dac: es8311_dac
|
||||
buffer_duration: 90ms
|
||||
use_apll: true
|
||||
```
|
||||
|
||||
All together we end up with a long block of configuration that looks like this:
|
||||
|
||||
```yaml
|
||||
i2s_audio:
|
||||
- id: i2s_audio_bus
|
||||
i2s_mclk_pin: GPIO42
|
||||
i2s_bclk_pin: GPIO9
|
||||
i2s_lrclk_pin:
|
||||
number: GPIO45
|
||||
ignore_strapping_warning: true
|
||||
|
||||
audio_adc:
|
||||
- platform: es7210
|
||||
id: es7210_adc
|
||||
bits_per_sample: $i2s_bps_mic
|
||||
sample_rate: $i2s_sample_rate_mic
|
||||
|
||||
audio_dac:
|
||||
- platform: es8311
|
||||
id: es8311_dac
|
||||
bits_per_sample: $i2s_bps_spk
|
||||
sample_rate: $i2s_sample_rate_spk
|
||||
|
||||
microphone:
|
||||
- platform: i2s_audio
|
||||
id: box_mic
|
||||
sample_rate: $i2s_sample_rate_mic
|
||||
i2s_din_pin: GPIO10
|
||||
bits_per_sample: $i2s_bps_mic
|
||||
adc_type: external
|
||||
|
||||
speaker:
|
||||
- platform: i2s_audio
|
||||
id: box_speaker
|
||||
i2s_dout_pin: GPIO8
|
||||
dac_type: external
|
||||
sample_rate: $i2s_sample_rate_spk
|
||||
bits_per_sample: $i2s_bps_spk
|
||||
audio_dac: es8311_dac
|
||||
buffer_duration: 90ms
|
||||
use_apll: true
|
||||
```
|
||||
|
||||
#### Final Configuration
|
||||
|
||||
There is a lot more config to go through, and I don't want to go over all of it in this blog, you can find all resources
|
||||
for the ESPHome portion of Katchi at my gitea repo.
|
||||
|
||||
{{< gitea server="https://git.toomuchtaco.net" repo="taco/voice-assistant" >}}
|
||||
|
||||
### Designing a kobold
|
||||
Reference in New Issue
Block a user