Skip to main content

Wio Terminal的以太网连接

这个wiki介绍了如何在Wio Terminal上使用 ENC28J60 OVERLAYS HAT for Raspberry Pi 来实现稳定的网络连接。这是在Wio Terminal上使用树莓派40 Pi扩展板的完美示例。

所需硬件

硬件连接

目前,如果您想测试软件,您可以使用导线连接。

  • 将以太网电缆插入ENC28J60 Overlays Hat。

安装UIPEthernet Arduino库

  1. 访问 UIPEthernet 存储库,并将整个存储库下载到本地驱动器。

  2. 现在,可以将库安装到Arduino IDE。打开Arduino IDE,点击 sketch -> Include Library -> Add .ZIP Library, 选择刚刚下载的 UIPEthernet UIPEthernet文件。

InstallLibrary

简单的DHCP示例

这个示例使用DHCP自动从网络主机获取网络配置。

示例代码

#include <UIPEthernet.h>

uint8_t mac[6] = {0x74,0x69,0x69,0x2D,0x30,0x31};

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while(!Serial);
Serial.println(F("[testDHCP]"));

Serial.print("MAC: ");
for (byte i = 0; i < 6; ++i) {
Serial.print(mac[i], HEX);
if (i < 5)
Serial.print(':');
}
Serial.println();

if (Ethernet.begin(mac) != 1) {
Serial.println("Failed to configure Ethernet using DHCP");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}

Serial.print("My IP: ");
Serial.println(Ethernet.localIP());
Serial.print("Netmask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS: ");
Serial.println(Ethernet.dnsServerIP());
}

void loop() {
// put your main code here, to run repeatedly:
}

通过静态IP连接网络

除了使用DHCP外,您还可以使用静态IP手动连接到网络主机以满足不同的需求。在这个例子中,您可以通过设置静态IP、子网掩码、网关和DNS来手动配置如何连接到网络。

示例代码

:::注 当您需要将设备连接到特定的网关和DNS(例如,旁路模式路由器/网关)时,这将非常有用。 :::

#include <UIPEthernet.h>

// Static Set-up, change the following according to your network
uint8_t mac[6] = {0x74,0x69,0x69,0x2D,0x30,0x31};
IPAddress myIP = {10,0,0,111};
IPAddress myMask = {255,255,255,0};
IPAddress myGatewayIP = {10,0,0,127};
IPAddress myDNS = {10,0,0,127};

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while(!Serial);
Serial.println(F("[getStaticIP]"));

Serial.print("MAC: ");
for (byte i = 0; i < 6; ++i) {
Serial.print(mac[i], HEX);
if (i < 5)
Serial.print(':');
}
Serial.println();

Ethernet.begin(mac,myIP, myDNS, myGatewayIP, myMask);

Serial.print("My IP: ");
Serial.println(Ethernet.localIP());
Serial.print("Netmask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS: ");
Serial.println(Ethernet.dnsServerIP());
}

void loop() {
// put your main code here, to run repeatedly:
}

简单的Web客户端

一旦我们通过以太网建立了网络连接,我们就可以将其用于TCP客户端。例如,从互联网获取数据(HTTP)或从同一网络中的服务器获取数据。

在此示例中,它首先使用DHCP进行设置,如果失败,则使用静态IP进行分配。此示例连接到 www.bing.com 并将数据打印到串行监视器。

示例代码

#include <UIPEthernet.h>

// Enter a MAC address for your controller below.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

char server[] = "www.bing.com";

// Set the static IP address to use if the DHCP fails to assign
IPAddress myIP(10, 0, 0, 187);
IPAddress myMask = {255,255,255,0};
IPAddress myGatewayIP = {10,0,0,127};
IPAddress dnsIP(10, 0, 0, 127);

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

// Variables to measure the speed
unsigned long beginMicros, endMicros;
unsigned long byteCount = 0;
bool printWebData = true; // set to false for better speed measurement

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

// start the Ethernet connection:
Serial.println("Initialize Ethernet with DHCP:");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac,myIP, dnsIP, myGatewayIP, myMask);
} else {
Serial.print(" DHCP assigned IP ");
Serial.println(Ethernet.localIP());
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.print("connecting to ");
Serial.print(server);
Serial.println("...");

// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.print("connected to ");
Serial.println(client.remoteIP());
// Make a HTTP request:
client.println("GET /search?q=WioTerminal HTTP/1.1");
client.println("Host: www.bing.com");
client.println("Connection: close");
client.println();
} else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
beginMicros = micros();
}

void loop() {
// if there are incoming bytes available
// from the server, read them and print them:
int len = client.available();
if (len > 0) {
byte buffer[80];
if (len > 80) len = 80;
client.read(buffer, len);
if (printWebData) {
Serial.write(buffer, len); // show in the serial monitor (slows some boards)
}
byteCount = byteCount + len;
}

// if the server's disconnected, stop the client:
if (!client.connected()) {
endMicros = micros();
Serial.println();
Serial.println("disconnecting.");
client.stop();
Serial.print("Received ");
Serial.print(byteCount);
Serial.print(" bytes in ");
float seconds = (float)(endMicros - beginMicros) / 1000000.0;
Serial.print(seconds, 4);
float rate = (float)byteCount / seconds / 1000.0;
Serial.print(", rate = ");
Serial.print(rate);
Serial.print(" kbytes/second");
Serial.println();

// do nothing forevermore:
while (true) {
delay(1);
}
}
}

Web服务器示例

另一方面,我们还可以将其设置为Web服务器,并允许同一网络中的其他设备连接到它(例如,读取Wio Terminal上观察到的传感器值)。由于以太网的稳定性要比Wi-Fi好得多,这在某些情况下非常有用。

示例代码

此示例将自身配置为Web服务器,并设置一个简单的网页,打印出从 A0A5 的值读数。您可以通过在同一网络中连接的计算机上的IP地址访问它。

#include <UIPEthernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(10, 0, 0, 123);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");

// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);

// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}

// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}

Web服务器测试

这还提供了一个使用该设置的简单测试示例。

这是在10小时内对Web服务器进行ping测试的屏幕截图。

  • 在相同的网络下,使用您的计算机对服务器的IP进行ping测试:
#include <UIPEthernet.h>

// Static IP Set-up
uint8_t mac[6] = {0x74,0x69,0x69,0x2D,0x30,0x31};
IPAddress myIP = {10,0,0,111};
EthernetServer server = EthernetServer(80);

void setup() {
Serial.begin(9600);
while(!Serial);
Ethernet.begin(mac, myIP);
server.begin();

Serial.print("My IP: ");
Serial.println(Ethernet.localIP());
Serial.print("Netmask: ");
Serial.println(Ethernet.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(Ethernet.gatewayIP());
Serial.print("DNS: ");
Serial.println(Ethernet.dnsServerIP());
}

void loop() {
// get client
EthernetClient client = server.available();
if(client && client.connected()) {
// do stuff (snipped but basically parses HTTP and responds with no other processing)
client.stop();
}
}

使用UDP进行NTP时间同步

在某些情况下, UDP 被用于网络通信。 NTP 就是一个很好的例子。下面的示例代码简单地从 time.nist.gov 服务器获取时间并打印到串行监视器上。

示例代码

#include <UIPEthernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

unsigned int localPort = 8888; // local port to listen for UDP packets

const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server

const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

// start Ethernet and UDP
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
} else if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// no point in carrying on, so do nothing forevermore:
while (true) {
delay(1);
}
}
Udp.begin(localPort);
}

void loop() {
sendNTPpacket(timeServer); // send an NTP packet to a time server

// wait to see if a reply is available
delay(1000);
if (Udp.parsePacket()) {
// We've received a packet, read the data from it
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:

unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Seconds since Jan 1 1900 = ");
Serial.println(secsSince1900);

// now convert NTP time into everyday time:
Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
Serial.println(epoch);

// print the hour, minute and second:
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
Serial.print(':');
if (((epoch % 3600) / 60) < 10) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
Serial.print(':');
if ((epoch % 60) < 10) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0');
}
Serial.println(epoch % 60); // print the second
}
// wait ten seconds before asking for the time again
delay(10000);
Ethernet.maintain();
}

// send an NTP request to the time server at the given address
void sendNTPpacket(const char * address) {
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;

// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); // NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}

发送 Twitter 示例

这是一个有趣的示例,使用Wio Terminal发送推文。它使用了 Tweet Library for Arduino 来绕过直接连接HTTPs的限制。

安装Arduino的Tweet Library

  1. 访问 Arduno-Twitter-library 仓库,并将整个仓库下载到本地驱动器上。

  2. 现在,可以将库安装到Arduino IDE中。打开Arduino IDE,点击sketch -> Include Library -> Add .ZIP Library, 选择刚刚下载的Arduno-Twitter-library 文件。

:::注 这是连接到Twitter的一种解决方案,可能不安全,请自行承担风险。 :::

获取令牌

点击这里获取一个使用OAuth进行消息发布的令牌。

请访问 http://arduino-tweet.appspot.com/ 获取更多参考信息

示例代码

  • 复制上述获取的令牌,并粘贴到Arduino代码中。
/*
* Check http://arduino-tweet.appspot.com/ for more reference
*/

#include <UIPEthernet.h>
#include <Twitter.h>

uint8_t mac[6] = {0x74,0x69,0x69,0x2D,0x30,0x31};

// Your Token to Tweet (get it from http://arduino-tweet.appspot.com/)
Twitter twitter("YOUR-TOKEN-HERE");

// Message to post
char msg[] = "Hello, World! I'm Arduino!";

void setup()
{
delay(1000);
Ethernet.begin(mac);
// or you can use DHCP for autoomatic IP address configuration.
// Ethernet.begin(mac);
Serial.begin(9600);
while(!Serial);

Serial.println("connecting ...");
if (twitter.post(msg)) {
// Specify &Serial to output received response to Serial.
// If no output is required, you can just omit the argument, e.g.
// int status = twitter.wait();
int status = twitter.wait(&Serial);
if (status == 200) {
Serial.println("OK.");
} else {
Serial.print("failed : code ");
Serial.println(status);
}
} else {
Serial.println("connection failed.");
}
}

void loop()
{
}
Loading Comments...