概要
使用U8G2库在oled显示屏上显示图像,esp8266上传网站控制页面,通过网页上的操作,更改屏幕显示
网站代码展示
网页index代码
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>EDA-Robot</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
text-align: center;
}
h1 {
text-align: center;
}
.button {
display: inline-block;
height: 30px;
width: 300px;
margin-top: 20px;
padding: 10px 20px;
background-color: deepskyblue;
color: #fff;
border: none;
border-radius: 20px; /* 添加圆角 */
text-decoration: none;
line-height: 2; /* 通过调整line-height的值来调整文字的垂直位置 */
text-align: center; /* 文字居中 */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* 添加立体感 */
transition: all 0.3s ease; /* 添加过渡效果 */
}
.button:hover {
background-color: skyblue; /* 鼠标悬停时的背景颜色 */
transform: translateY(2px); /* 点击效果 */
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3); /* 添加更多立体感 */
}
</style>
</head>
<body>
<div class='container'>
<h1>EDA-Robot控制中心</h1>
<h3>180度限位舵机版</h3>
<p>本项目基于ESP8266主控开发</p>
<input type='button' style="height: 50px;width: 320px" class='button' value="遥控器"onclick="window.location.href='./control.html'">
<input type='button' style="height: 50px;width: 320px" class='button' value="配置"onclick="window.location.href='./setting.html'">
<input type='button' style="height: 50px; width: 320px" class='button' value="嘉立创EDA">
<a href="https://lceda.cn/">
<table class="container button" style="height: 200px">
<tr>
<th>设备名称:</th>
<td>EDA-Robot</td>
</tr>
<tr>
<th>内存大小:</th>
<td>4MB</td>
</tr>
<tr>
<th>控制台版本:</th>
<td>V1.0</td>
</tr>
<tr>
<th>官网:</th>
<td> <a href="https://lceda.cn/">嘉立创EDA</a></td>
</tr>
</table>
</a>
</div>
</body>
</html>
网页control代码
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>EDA-Robot</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
text-align: center;
}
h1 {
text-align: center;
}
button {
display: inline-block;
height: auto;
width: auto;
margin-top: 20px;
padding: 10px 20px;
background-color: deepskyblue;
color: #fff;
border: none;
border-radius: 20px; /* 添加圆角 */
text-decoration: none;
line-height: 2; /* 通过调整line-height的值来调整文字的垂直位置 */
text-align: center; /* 文字居中 */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* 添加立体感 */
transition: all 0.3s ease; /* 添加过渡效果 */
}
button:hover {
background-color: skyblue; /* 鼠标悬停时的背景颜色 */
transform: translateY(2px); /* 点击效果 */
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3); /* 添加更多立体感 */
}
.button-grid3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
justify-content: center;
align-content: center;
text-align: center;
margin: 20px;
}
.button-grid2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
justify-content: center;
align-content: center;
text-align: center;
margin: 20px;
} .button-grid1 {
display: grid;
border-radius: 20px; /* 添加圆角 */
grid-template-columns: repeat(1, 1fr);
justify-content: center;
align-content: center;
text-align: center;
margin: 10px;
}
</style>
<script>
// 简化 AJAX 请求函数
function sendCommand(action) {
fetch(`/${action}`)
.then(response => response.text())
.catch(() => alert('发送失败,请检查设备连接'));
}
function refreshState(url, displayElementId) {
fetch(url)
.then(response => response.text())
.then(data => {
document.getElementById(displayElementId).innerText = data;
});
}
function setRefreshInterval(url, displayElementId) {
setInterval(() => refreshState(url, displayElementId), 1000);
}
const states = [
{ url: '/batteryVoltage', displayId: 'batteryVoltageDisplay' },
{ url: '/batteryPercentage', displayId: 'batteryPercentageDisplay' },
];
states.forEach(state => setRefreshInterval(state.url, state.displayId));
</script>
</head>
<body>
<div class='container'>
<h1>EDA-Robot遥控台</h1>
<p>本项目基于ESP8266主控开发</p >
<div class="button-grid2" style="display: flex; justify-content: center;">
<button style="margin-right: 70px"><p>电压:<span id="batteryVoltageDisplay">0</span></p></button>
<button style="margin-left: 70px"><p>电量:<span id="batteryPercentageDisplay">0</span></p></button>
</div>
<!-- 运动控制 -->
<div class="button-grid1" style="background-color: papayawhip">
<h3>运动控制</h3>
<div class="button-grid1"style="display: flex; justify-content: center;">
<button onclick="sendCommand('front')">↑</button>
</div>
<div class="button-grid2" style="display: flex; justify-content: center;">
<button onclick="sendCommand('left')" style="margin-right: 70px">←</button>
<button onclick="sendCommand('right')" style="margin-left: 70px">→</button>
</div>
<div class="button-grid1" style="display: flex; justify-content: center;">
<button onclick="sendCommand('back')">↓</button>
</div>
<div class="button-grid3">
<button onclick="sendCommand('toplefthand')">抬左手</button>
<button onclick="sendCommand('toprighthand')">抬右手</button>
<button onclick="sendCommand('sitdown')">坐下</button>
<button onclick="sendCommand('lie')">趴下</button>
<button onclick="sendCommand('free')">自由模式开</button>
<button onclick="sendCommand('offfree')">自由模式关</button>
</div>
<div class="button-grid1">
<button onclick="sendCommand('sleep')">回收</button>
</div>
</div>
<!-- 表情控制 -->
<div class="button-grid1" style="background-color: limegreen">
<h3>表情控制</h3>
<div class="button-grid3" >
<button onclick="sendCommand('histate')">开心</button>
<button onclick="sendCommand('angrystate')">生气</button>
<button onclick="sendCommand('sickstate')">难受</button>
<button onclick="sendCommand('dowhatstate')">好奇</button>
<button onclick="sendCommand('lovestate')">喜欢</button>
<button onclick="sendCommand('errorstate')">错误</button>
<button onclick="sendCommand('yunstate')">晕</button>
<button onclick="sendCommand('edastate')">嘉立创LOGO</button>
</div>
</div>
<!-- 联网功能 -->
<div class="button-grid1" style="background-color: orange">
<h3>联网功能</h3>
<div class="button-grid2">
<button onclick="sendCommand('time')">时间</button>
<button onclick="sendCommand('weather')">天气</button>
</div>
</div>
</div>
</body>
</html>
网页setting代码
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>EDA-Robot</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
text-align: center;
}
h1 {
text-align: center;
}
.button {
display: inline-block;
height: 30px;
width: 300px;
margin-top: 20px;
padding: 10px 20px;
background-color: deepskyblue;
color: #fff;
border: none;
border-radius: 20px; /* 添加圆角 */
text-decoration: none;
line-height: 2; /* 通过调整line-height的值来调整文字的垂直位置 */
text-align: center; /* 文字居中 */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* 添加立体感 */
transition: all 0.3s ease; /* 添加过渡效果 */
}
.button:hover {
background-color: skyblue; /* 鼠标悬停时的背景颜色 */
transform: translateY(2px); /* 点击效果 */
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3); /* 添加更多立体感 */
}
.search-box {
margin-top: 20px;
display: inline-block;
height: 30px;
width: 300px;
padding: 5px 10px;
background-color: #f0f0f0;
border: 1px solid #ccc;
border-radius: 20px;
text-align: center; /* 文字居中 */
}
.hidden {
display: none; /* 初始隐藏 */
}
</style>
</head>
<body>
<form action='/connect' method='POST'>
<div class='container'>
<h1>EDA-Robot设备配置页</h1>
<p>本项目基于ESP8266主控开发</p>
<input type='text' name='ssid' placeholder='输入WIFI名称' class='search-box'>
<input type='password' name='pass' placeholder='输入WIFI密码' class='search-box'>
<input type='uid' name='uid' placeholder='输入bilibili用户ID' class='search-box'>
<input type='api' name='api' placeholder='输入心知天气API密钥' class='search-box'>
<input type='city' name='city' placeholder='输入城市拼音小写' class='search-box'>
<input type='submit' style="height: 50px;width: 320px" class='button' value="保存">
<a href="https://lceda.cn/">
<table class="container button" style="height: 200px">
<tr>
<th>设备名称:</th>
<td>EDA-Robot</td>
</tr>
<tr>
<th>内存大小:</th>
<td>4MB</td>
</tr>
<tr>
<th>控制台版本:</th>
<td>V1.0</td>
</tr>
<tr>
<th>官网:</th>
<td> <a href="https://lceda.cn/">嘉立创EDA</a></td>
</tr>
</table>
</a>
</div>
</form>
</body>
</html>
嵌入式代码展示
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <U8g2lib.h>
#include <Wire.h>
#include "image.cpp"
AsyncWebServer server(80);
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/5, /* data=*/4); // ESP32 Thing, HW I2C with pin remapping
int emojiState = 0;
int prevEmojiState = -1;
const char* ssid = "xinxin";
const char* password = "xinxin1102";
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
void setup() {
Serial.begin(115200);
SPIFFS.begin();
u8g2.begin(); // start the u8g2 library
u8g2.setDisplayRotation(U8G2_R2);
u8g2.firstPage();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{
// 检查SPIFFS文件系统中是否存在index.html文件
if (SPIFFS.exists("/index.html")) {
fs::File file = SPIFFS.open("/index.html", "r"); // 打开index.html文件
if (file) {
size_t fileSize = file.size(); // 获取文件大小
String fileContent;
// 逐字节读取文件内容
while (file.available()) {
fileContent += (char)file.read();
}
file.close(); // 关闭文件
// 返回HTML内容
request->send(200, "text/html", fileContent);
return;
}
}
// 如果文件不存在,返回404错误
request->send(404, "text/plain", "File Not Found"); });
server.on("/control.html", HTTP_GET, [](AsyncWebServerRequest *request)
{
// 检查SPIFFS文件系统中是否存在index.html文件
if (SPIFFS.exists("/control.html")) {
fs::File file = SPIFFS.open("/control.html", "r"); // 打开index.html文件
if (file) {
size_t fileSize = file.size(); // 获取文件大小
String fileContent;
// 逐字节读取文件内容
while (file.available()) {
fileContent += (char)file.read();
}
file.close(); // 关闭文件
// 返回HTML内容
request->send(200, "text/html", fileContent);
return;
}
}
// 如果文件不存在,返回404错误
request->send(404, "text/plain", "File Not Found"); });
server.on("/setting.html", HTTP_GET, [](AsyncWebServerRequest *request)
{
// 检查SPIFFS文件系统中是否存在index.html文件
if (SPIFFS.exists("/setting.html")) {
fs::File file = SPIFFS.open("/setting.html", "r"); // 打开index.html文件
if (file) {
size_t fileSize = file.size(); // 获取文件大小
String fileContent;
// 逐字节读取文件内容
while (file.available()) {
fileContent += (char)file.read();
}
file.close(); // 关闭文件
// 返回HTML内容
request->send(200, "text/html", fileContent);
return;
}
}
// 如果文件不存在,返回404错误
request->send(404, "text/plain", "File Not Found"); });
server.on("/histate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 0; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/angrystate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 1; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/errorstate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 2; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/dowhatstate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 3; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/lovestate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 4; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/sickstate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 5; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/yunstate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 6; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.on("/edastate", HTTP_GET, [](AsyncWebServerRequest *request)
{
emojiState = 9; // 设置标志,oled显示
request->send(200, "text/plain", "Front function started"); });
server.begin();
}
void loop() {
if (emojiState != prevEmojiState)
{
u8g2.clearDisplay(); // 状态变化时清屏
prevEmojiState = emojiState; // 更新状态
}
switch (emojiState)
{
case 0: // 首页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, 0, 128, 64, hi);
} while (u8g2.nextPage());
break;
case 1: // 第二页
u8g2.setFont(u8g2_font_ncenB14_tr);
do
{
u8g2.drawXBMP(0, 0, 128, 64, angry);
} while (u8g2.nextPage());
break;
case 2: // 第三页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, 0, 128, 64, error);
} while (u8g2.nextPage());
break;
case 3: // 第四页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, 0, 128, 64, dowhat);
} while (u8g2.nextPage());
break;
case 4: // 第四页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, 0, 128, 64, love);
} while (u8g2.nextPage());
break;
case 5: // 第四页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, 0, 128, 64, sick);
} while (u8g2.nextPage());
break;
case 6: // 第四页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, 0, 128, 64, yun);
} while (u8g2.nextPage());
break;
case 9: // 第四页
do
{
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawXBMP(0, (64 / 2 - 22 / 2), 128, 22, logo);
} while (u8g2.nextPage());
break;
default:
// 添加默认 case 来处理其他情况
break;
}
delay(100);
}
相关视频
【PlatformIO】基于Arduino的ESP8266 网页控制oled图像