mirror of
https://github.com/playfultechnology/esp32-eyes.git
synced 2025-12-06 17:15:42 -08:00
Updated readme and fixed typos
This commit is contained in:
@@ -84,7 +84,7 @@ void FaceBehavior::GoToEmotion(eEmotions emotion) {
|
|||||||
case eEmotions::Annoyed: _face.Expression.GoTo_Annoyed(); break;
|
case eEmotions::Annoyed: _face.Expression.GoTo_Annoyed(); break;
|
||||||
case eEmotions::Surprised: _face.Expression.GoTo_Surprised(); break;
|
case eEmotions::Surprised: _face.Expression.GoTo_Surprised(); break;
|
||||||
case eEmotions::Skeptic: _face.Expression.GoTo_Skeptic(); break;
|
case eEmotions::Skeptic: _face.Expression.GoTo_Skeptic(); break;
|
||||||
case eEmotions::Fustrated: _face.Expression.GoTo_Fustrated(); break;
|
case eEmotions::Frustrated: _face.Expression.GoTo_Frustrated(); break;
|
||||||
case eEmotions::Unimpressed: _face.Expression.GoTo_Unimpressed(); break;
|
case eEmotions::Unimpressed: _face.Expression.GoTo_Unimpressed(); break;
|
||||||
case eEmotions::Sleepy: _face.Expression.GoTo_Sleepy(); break;
|
case eEmotions::Sleepy: _face.Expression.GoTo_Sleepy(); break;
|
||||||
case eEmotions::Suspicious: _face.Expression.GoTo_Suspicious(); break;
|
case eEmotions::Suspicious: _face.Expression.GoTo_Suspicious(); break;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ enum eEmotions {
|
|||||||
Annoyed,
|
Annoyed,
|
||||||
Surprised,
|
Surprised,
|
||||||
Skeptic,
|
Skeptic,
|
||||||
Fustrated,
|
Frustrated,
|
||||||
Unimpressed,
|
Unimpressed,
|
||||||
Sleepy,
|
Sleepy,
|
||||||
Suspicious,
|
Suspicious,
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ void FaceExpression::GoTo_Skeptic()
|
|||||||
_face.LeftEye.TransitionTo(Preset_Skeptic_Alt);
|
_face.LeftEye.TransitionTo(Preset_Skeptic_Alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FaceExpression::GoTo_Fustrated()
|
void FaceExpression::GoTo_Frustrated()
|
||||||
{
|
{
|
||||||
ClearVariations();
|
ClearVariations();
|
||||||
_face.RightEye.TransitionTo(Preset_Fustrated);
|
_face.RightEye.TransitionTo(Preset_Fustrated);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class FaceExpression {
|
|||||||
void GoTo_Annoyed();
|
void GoTo_Annoyed();
|
||||||
void GoTo_Surprised();
|
void GoTo_Surprised();
|
||||||
void GoTo_Skeptic();
|
void GoTo_Skeptic();
|
||||||
void GoTo_Fustrated();
|
void GoTo_Frustrated();
|
||||||
void GoTo_Unimpressed();
|
void GoTo_Unimpressed();
|
||||||
void GoTo_Sleepy();
|
void GoTo_Sleepy();
|
||||||
void GoTo_Suspicious();
|
void GoTo_Suspicious();
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -6,10 +6,39 @@ Inspired by the expressive eye animations of the Anki "Cozmo" robot, this Arduin
|
|||||||
<img src="https://github.com/playfultechnology/esp32-eyes/blob/main/doc/anki-cozmo-faces-3-1024x576.jpg" />
|
<img src="https://github.com/playfultechnology/esp32-eyes/blob/main/doc/anki-cozmo-faces-3-1024x576.jpg" />
|
||||||
|
|
||||||
|
|
||||||
Unlike some libraries which require a set of bitmap images for each frame of animation, this library draws each frame dynamically from a programmatic set of parameters.
|
Unlike some libraries which display a set of pre-rendered bitmap images for each frame of animation, this library draws each frame dynamically from a programmatic set of parameters.
|
||||||
|
|
||||||
Heavily based on <a href="https://github.com/luisllamasbinaburo/ESP32_Faces/">this library</a>, although with significant adjustments:
|
Heavily based on <a href="https://github.com/luisllamasbinaburo/ESP32_Faces/">this library</a>, although with significant adjustments:
|
||||||
|
|
||||||
- OLED (using <a href="https://github.com/olikraus/u8g2">u8g2</a>) rather than TFT (based on <a href="https://github.com/Bodmer/TFT_eSPI">eSPI_TFT</a>)
|
- OLED (using <a href="https://github.com/olikraus/u8g2">u8g2</a>) rather than TFT (based on <a href="https://github.com/Bodmer/TFT_eSPI">eSPI_TFT</a>)
|
||||||
- Horizontal rather than vertical alignment
|
- Horizontal rather than vertical alignment
|
||||||
- Mirrored left/right eye animations
|
- Mirrored left/right eye animations
|
||||||
|
- Automatic or manual blink and look direction
|
||||||
|
|
||||||
|
## Component Structure
|
||||||
|
|
||||||
|
- *Face* is the core object, consisting of left and right eye components, behaviour, expression, a look assistant, and a blink assistant. The outputs of these components are chained together to create the display on each frame:
|
||||||
|
|
||||||
|
- The Face *Behaviour* contains an array of weighted _Emotions_. There are currently 18 emotions, as defined in the enum in FaceEmotions.hpp.
|
||||||
|
Each emotion can have an individual weight assigned to it, as follows:
|
||||||
|
```
|
||||||
|
face->Behavior.SetEmotion(eEmotions::Glee, 1.0);
|
||||||
|
face->Behavior.SetEmotion(eEmotions::Anger, 0.5);
|
||||||
|
```
|
||||||
|
If ```face->RandomBehavior = true;``` (which is the default), then Face will use a roulette-wheel selection to randomly assign a new emotion based on their relative weights.
|
||||||
|
The frequency with which the current emotion is re-evaluated (although this does not always result in a change) is determined by the value passed to ```face->Behaviour.Timer.SetIntervalMillis();```
|
||||||
|
(If no weights have been assigned to any emotion, the face will default to "normal" emotion).
|
||||||
|
Note that emotions are not blended together - the "weight" assigned to them determines the chances with which any emotion will be selected to be the next emotion (currentEmotion)
|
||||||
|
|
||||||
|
- *Expression* is a wrapper that handles transitions of each eye to the currently selected emotion.
|
||||||
|
|
||||||
|
- The Blink assistant handles blinking. If ```face->RandomBlink = true;``` (the default), the eyes will automatically blink, with a frequency determined by the value passed to ```face->Blink.Timer.SetIntervalMillis();```
|
||||||
|
The eyes may be blinked manually by calling ```face->DoBlink();```
|
||||||
|
|
||||||
|
- The Look assistant handles the global position of the eyes around the screen. If ```face->RandomLook = true;``` (the default), the eyes will randomly move around the screen, with a frequency determined by the value passed to ```face->Look.Timer.SetIntervalMillis();```
|
||||||
|
The eyes may be set to look at any position by calling ```face->Look.LookAt(x, y);``` (where x and y range from -1.0 - 1.0)
|
||||||
|
|
||||||
|
|
||||||
|
- Each eye is responsible for managing their own drawing operations to the display (in EyeDrawer.cpp)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
/***************************************************
|
/***************************************************
|
||||||
Copyright (c) 2020 Luis Llamas
|
* ESP32-Eyes, Copyright (c) 2023 Alastair Aitchison, Playful Technology
|
||||||
(www.luisllamas.es)
|
* Based on previous work by Luis Llamas (www.luisllamas.es)
|
||||||
|
*
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by
|
****************************************************/
|
||||||
the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses
|
|
||||||
****************************************************/
|
|
||||||
|
|
||||||
// INCLUDES
|
// INCLUDES
|
||||||
// Built-in Arduino I2C library
|
// Built-in Arduino I2C library
|
||||||
@@ -17,36 +11,18 @@ You should have received a copy of the GNU Affero General Public License along w
|
|||||||
#include "Face.h"
|
#include "Face.h"
|
||||||
|
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
|
const byte joystickPins[] = {26, 25};
|
||||||
const byte blinkPin = 16;
|
const byte blinkPin = 16;
|
||||||
|
|
||||||
// GLOBALS
|
// GLOBALS
|
||||||
Face *face;
|
Face *face;
|
||||||
String emotionName[] = {
|
|
||||||
"Normal",
|
|
||||||
"Angry",
|
|
||||||
"Glee",
|
|
||||||
"Happy",
|
|
||||||
"Sad",
|
|
||||||
"Worried",
|
|
||||||
"Focused",
|
|
||||||
"Annoyed",
|
|
||||||
"Surprised",
|
|
||||||
"Skeptic",
|
|
||||||
"Frustrated",
|
|
||||||
"Unimpressed",
|
|
||||||
"Sleepy",
|
|
||||||
"Suspicious",
|
|
||||||
"Squint",
|
|
||||||
"Furious",
|
|
||||||
"Scared",
|
|
||||||
"Awe"
|
|
||||||
};
|
|
||||||
|
|
||||||
void setup(void) {
|
void setup(void) {
|
||||||
// Create a serial connection
|
// Create a serial connection
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println(__FILE__ __DATE__);
|
Serial.println(__FILE__ __DATE__);
|
||||||
|
|
||||||
|
// Configure input pins
|
||||||
pinMode(blinkPin, INPUT_PULLUP);
|
pinMode(blinkPin, INPUT_PULLUP);
|
||||||
|
|
||||||
// Create a new face
|
// Create a new face
|
||||||
@@ -58,18 +34,16 @@ void setup(void) {
|
|||||||
face->Behavior.SetEmotion(eEmotions::Normal, 1.0);
|
face->Behavior.SetEmotion(eEmotions::Normal, 1.0);
|
||||||
//face->Behavior.SetEmotion(eEmotions::Angry, 1.0);
|
//face->Behavior.SetEmotion(eEmotions::Angry, 1.0);
|
||||||
//face->Behavior.SetEmotion(eEmotions::Sad, 1.0);
|
//face->Behavior.SetEmotion(eEmotions::Sad, 1.0);
|
||||||
// Automatically select a random behaviour (based on the weight assigned to each emotion)
|
// Automatically switch between possible allowed behaviours (selecting new behaviour randomly based on the weight assigned to each emotion)
|
||||||
face->RandomBehavior = true;
|
face->RandomBehavior = true;
|
||||||
|
|
||||||
// Automatically blink
|
// Automatically blink
|
||||||
face->RandomBlink = true;
|
face->RandomBlink = true;
|
||||||
// Set blink rate
|
// Set blink rate
|
||||||
face->Blink.Timer.SetIntervalMillis(4000);
|
face->Blink.Timer.SetIntervalMillis(4000);
|
||||||
//face->Blink.Timer.Stop();
|
|
||||||
|
|
||||||
// Automatically choose a new random direction to look
|
// Automatically choose a new random direction to look
|
||||||
face->RandomLook = true;
|
face->RandomLook = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
|
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||||
@@ -87,7 +61,8 @@ float mapFloat(float x, float in_min, float in_max, float out_min, float out_max
|
|||||||
void loop(){
|
void loop(){
|
||||||
static int lastMoveTime;
|
static int lastMoveTime;
|
||||||
|
|
||||||
// To avoid making eyes too twitchy (and to allow time for previous animation to end), we only recalculate new position every 500ms
|
// To avoid making eyes too twitchy (and to allow time for previous move animation to end),
|
||||||
|
// only recalculate new position every 500ms
|
||||||
if(millis() - lastMoveTime > 500) {
|
if(millis() - lastMoveTime > 500) {
|
||||||
int yRaw = analogRead(25);
|
int yRaw = analogRead(25);
|
||||||
int xRaw = analogRead(26);
|
int xRaw = analogRead(26);
|
||||||
@@ -96,11 +71,11 @@ void loop(){
|
|||||||
face->Look.LookAt(x, y);
|
face->Look.LookAt(x, y);
|
||||||
lastMoveTime = millis();
|
lastMoveTime = millis();
|
||||||
}
|
}
|
||||||
|
// Blink when joystick pressed in
|
||||||
if(!digitalRead(blinkPin)){
|
if(!digitalRead(blinkPin)){
|
||||||
face->DoBlink();
|
face->DoBlink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Use this code to set a particular emotion from a button
|
// Use this code to set a particular emotion from a button
|
||||||
int32_t potValue = analogRead(15);
|
int32_t potValue = analogRead(15);
|
||||||
@@ -108,31 +83,6 @@ void loop(){
|
|||||||
face->Behavior.SetEmotion(eEmotions::Angry, anger);
|
face->Behavior.SetEmotion(eEmotions::Angry, anger);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
// Update the face!
|
||||||
// Use this code to cycle automatically through all emotions
|
|
||||||
static uint32_t counter = millis();
|
|
||||||
static uint8_t emotionno = 0;
|
|
||||||
static uint8_t changeEmotionFlag = 0;
|
|
||||||
static uint8_t n = 0;
|
|
||||||
|
|
||||||
if(millis() - counter > 6000) {
|
|
||||||
counter = millis();
|
|
||||||
emotionno = n++;
|
|
||||||
if(n >= EMOTIONS_COUNT) n = 0;
|
|
||||||
changeEmotionFlag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(changeEmotionFlag) {
|
|
||||||
// Clear any previously assigned weights
|
|
||||||
face->Behavior.Clear();
|
|
||||||
// Assign weight of 1.0 to the next emotion in the list
|
|
||||||
face->Behavior.SetEmotion((eEmotions)emotionno, 1.0);
|
|
||||||
// Print the new emotion to the serial monitor
|
|
||||||
Serial.println(emotionName[emotionno]);
|
|
||||||
// Reset the flag
|
|
||||||
changeEmotionFlag = 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
face->Update();
|
face->Update();
|
||||||
//delay(10);
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user