昨天我分别用arduino
(昨天全篇都把这个单词拼错了)和8266
点亮了OLED
,感觉还是很好玩的,而且很有成就感,这个成就感最大的来源是,终于在硬件方面有了一点点突破,当然之前没突破的原因可能是时机不成熟。
今天我发现树莓派其实也是可以点亮oled
的,而且树莓派新能更强,按理说可玩性应该很高,没玩起来可能还是实力不够,不过现在这些都已经成为过去了,毕竟万事开头难,昨天开了一个好头,后面应该会越来越顺的。
今天我们要分享下如何用8266
搭建一个微型服务器,目前我找到两种解决方案,一种是普通的web
服务器(类似于我之前写过的syske-boot
),另一种是webservice
,从传输数据的灵活性方面来看,后一种更灵活,也更方便,下面我们具体来看下如何实现。
在开始之前,我们先简单介绍下Arduino IDE
。
从事开发工作的小伙伴应该对IDE
都不陌生,所有的语言都有自己的IDE
,它的中文意思是集成开发环境,所以Arduino IDE
就是Arduino
的集成开发环境,除了Arduino IDE
之外,我们还可以用VS CODE
开发Arduino
。
Arduino IDE
的安装很简单,直接下载安装文件双击运行即可。当然,你也可以下载便携版,这个版本是免安装的。
目前最新版本是1.8.15
,左下方的选项是下载安装版的,右上方的ZIP File
选项是下载免安装版的。
下载安装之后,首次打开长这个样子:
主要区域有三块,菜单栏(工具栏)、代码区(写代码的地方)、终端。大部分IDE
都包括这个三个分区。
菜单栏五个图标分别表示
- 第一个表示编译代码,主要用于检查代码是否有编译错误
- 第二个表示将代码上传到开发板中,在此之前要先安装好开发板的驱动,然后选择对应的串口号
- 第三个是新建项目
- 第四个是打开,主要用了打开新项目
- 第五个是保存,用于保存当前项目
出了这个几个常用的菜单外,还有几个菜单我们会经常用到:
第一个是管理库,就是用来管理Arduino
的第三方库的,比如ESP8266
之类的,我们可以在这个菜单下下载新的库,目前第三方库特别多:
下面那个端口菜单,主要是用来切换端口的,一般我们开发板连接电脑后,安装完驱动之后,系统会给他分配串口号,具体串口号可以去设备管理器下查看:
好了,关于Arduino IED
我们暂时就先说这么多,有不清楚的小伙伴可以留言或者私信。
下面我们就直接上代码了:
#include <ESP8266WiFi.h>;
#include <ArduinoWiFiServer.h>;
#include <SPI.h>; // 加载SPI库
#include <Wire.h>; // 加载Wire库
#include <Adafruit_GFX.h>; // 加载Adafruit_GFX库
#include <Adafruit_SSD1306.h>; // 加载Adafruit_SSD1306库
// 定义 OLED屏幕的分辨率
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
// WiFi parameters
const char* ssid = "wifi name";
const char* password = "wifi-password";
// 创建服务器实例,并指定服务器端口
ArduinoWiFiServer server(2323);
String infoStr = "";
String ip = "";
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 设置OLED的I2C地址
display.clearDisplay(); // 清空屏幕
display.setTextSize(2); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
display.setCursor(0, 0); // 设置开始显示文字的坐标
display.println("Hello World!"); // 输出的字符
display.println(" by syske");
display.display(); // 使更改的显示生效
delay(1000);
Serial.begin(9600); // 设置串口波特率
Serial.println("OLED FeatherWing test"); // 串口输出
delay(10);
// 必须采用 AP 与 Station 兼容模式
WiFi.mode(WIFI_AP_STA);
delay(500);
// 等待配网
// WiFi.beginSmartConfig();
// Connect to WiFi
WiFi.begin(ssid, password);
// 收到配网信息后ESP8266将自动连接,WiFi.status 状态就会返回:已连接
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
// 完成连接,退出配网等待。
Serial.println(WiFi.smartConfigDone());
}
ip = WiFi.localIP().toString();
display.println("IP: " + ip); // 输出的字符
display.display(); // 使更改的显示生效
server.begin();
// 串口数据打印,这里主要是为了方便调试
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// put your main code here, to run repeatedly:
WiFiClient client = server.available(); // returns first client which has data to read or a 'false' client
Serial.println(client);
if (client) { // client is true only if it is connected and has data to read
String s = client.readStringUntil('\n'); // read the message incoming from one of the clients
s.trim(); // trim eventual \r
Serial.println(s); // print the message to Serial Monitor
if (s.length() > 0) {
infoStr = String(infoStr + "\n" + s);
display.clearDisplay(); // 清空屏幕
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
display.setCursor(0, 0); // 设置开始显示文字的坐标
display.print("IP: " + ip); // 输出的字符
display.println(infoStr); // 输出的字符
display.display(); // 使更改的显示生效
client.print("HTTP/1.1 OK\nContent-Type:text/html\n\r\n<html><head><link rel=\"icon\" href=\"data:;base64,=\"></head><body>hello 8266</body></html>"); // this is only for the sending client
server.println(s); // send the message to all connected clients
server.flush(); // flush the buffers
client.stop();
}
}
}
代码都比较基础,这里做一个简单说明。首先我们引入了ESP8266WiFi
的依赖,这个依赖就是我们8266
开发板的依赖,我们主要是通过这个依赖对我们的开发板进行配网;另外一个依赖是ArduinoWiFiServer
,这个依赖主要是用来搭建web
服务器的;剩下的依赖都是OLED
的依赖,主要是为了把我们的请求数据打印出来,方便查看。
再接着就是我们基础的代码了:
- 定义屏幕、
wifi名称和密码
、初始化服务器,然后在setup
方法内,我们先打印了一段文字,然后进行了配网操作,最后打印服务器ip
地址,并启动服务器。 - 在
loop
方法内部,我们进行服务端监听,如果收到客户端请求,则会接收服务端请求数据,给客户端发送响应数据,然后把请求数据打印输出到屏幕上。
我直接通过电脑访问(确保在同一个wifi
下):
服务端显示效果如下:
我们同样也是直接上代码,相比与前面的web
服务器,websocket
服务器的代码要少一些:
#include <ArduinoWebsockets.h>
#include <ESP8266WiFi.h>
#include <Wire.h>; // 加载Wire库
#include <Adafruit_GFX.h>; // 加载Adafruit_GFX库
#include <Adafruit_SSD1306.h>; // 加载Adafruit_SSD1306库
// 定义 OLED屏幕的分辨率
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
// WiFi parameters
const char* ssid = "wifi name";
const char* password = "wifi-password";
String ip = "";
using namespace websockets;
WebsocketsServer server;
void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 设置OLED的I2C地址
display.clearDisplay(); // 清空屏幕
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
display.setCursor(0, 0); // 设置开始显示文字的坐标
// Connect to wifi
WiFi.begin(ssid, password);
// Wait some time to connect to wifi
for (int i = 0; i < 15 && WiFi.status() != WL_CONNECTED; i++) {
Serial.print(".");
delay(1000);
}
ip = WiFi.localIP().toString();
display.println("IP: " + ip); // 输出的字符
display.display(); // 使更改的显示生效
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP()); //You can get IP address assigned to ESP
server.listen(80);
Serial.print("Is server live? ");
Serial.println(server.available());
}
void loop() {
auto client = server.accept();
if (client.available()) {
auto msg = client.readBlocking();
// log
Serial.print("Get Message: ");
Serial.println(msg.data());
// return echo
client.send("Echo: " + msg.data());
// close the connection
client.close();
display.clearDisplay(); // 清空屏幕
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
display.setCursor(0, 0); // 设置开始显示文字的坐标
display.println("IP: " + ip); // 输出的字符
display.println("message: " + msg.data()); // 输出的字符
display.display(); // 使更改的显示生效
}
delay(1000);
}
大部分代码都是相同的,不同点大致如下:
-
依赖变了,
websocket
的依赖包变成了ArduinoWebsockets
-
服务器初始化变了,直接实例化
WebsocketsServer
,然后指定监听端口server.listen(80);
-
读取数据变成了
websocket
的方式:auto client = server.accept(); if (client.available()) { auto msg = client.readBlocking(); }
其实最大的改变是,客户端发送数据的方式变了。第一种方式最大的问题是不方便数据的解析,
http
本质上就是socket
,所以socket
是会出现阻塞问题,我们之前手写web
服务器的时候就遇到过,最后是通过NIO
解决的,但是用webscoekt
是没有这个问题的,直接发送的就是数据,基本上都不需要解析。以为我的设想是是通过客户端把需要展示的数据发送到服务器端(
8266
),所以8266
作为服务端是最好的选择。这里我的客户端用的是python
,写起来很快,用起来很方便:from websocket import create_connection ws = create_connection("ws://192.168.0.102:80") print("Sending 'Hello, World'...") ws.send("syske master") print("Sent") print("Receiving...") result = ws.recv() print("Received '%s'" % result) ws.close()
短短几行代码就搞定了,上面的代码就是给服务器发送一段文字,
8266
收到我们的消息后,会把我们的消息展示在屏幕上。下面我们看下效果:
8266
可玩性确实比较高,特别是它的wifi
功能,简直不要太强。好了,今天的内容就分享这么多吧,后面我会不定期给大家分享arduino
的相关内容的。各位小伙伴,晚安哦!