roc2

  • 2019-12-11
  • 发表了主题帖: 【零知ESP8266教程】进阶篇3 SSDP简单服务发现协议​

    1、概述 SSDP简单服务发现协议,它是UPnP的核心协议之一。UPnP是零配置网络协议的一种。大众使用的家庭设备一般都支持这个协议,以便用户的主机或手机能够轻松发现这些设备。当一个新的设备(比如说笔记本)加入到网络中时,它可以向本地网络查询特定设备是否存在,这些设备包括互联网网关、音频系统、TV或者打印机等。下面在零知开源平台上进行该功能的测试。 2、软件和硬件 硬件我们本次使用零知-ESP8266; 软件使用零知开发工具(持续更新中),自带示例: 3、方法步骤 (1)先在零知开发工具中打开SSDP示例,或者复制下面的代码到零知开发工具中: /********************************************************** *    文件: x.ino      by 零知实验室(www.lingzhilab.com) *    -^^- 零知开源,让电子制作变得更简单! -^^- *    时间: 2019/05/28 12:22 *    说明: ************************************************************/ #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <ESP8266SSDP.h>    #ifndef STASSID #define STASSID "ssid" #define STAPSK  "passwd" #endif    const char* ssid = STASSID; const char* password = STAPSK;    ESP8266WebServer HTTP(80);    void setup() {   Serial.begin(115200);   Serial.println();   Serial.println("Starting WiFi...");      WiFi.mode(WIFI_STA);   WiFi.begin(ssid, password);   if (WiFi.waitForConnectResult() == WL_CONNECTED) {        Serial.printf("Starting HTTP...\n");     HTTP.on("/index.html", HTTP_GET, []() {       HTTP.send(200, "text/plain", "Hello World!");     });     HTTP.on("/description.xml", HTTP_GET, []() {       SSDP.schema(HTTP.client());     });     HTTP.begin();        Serial.printf("Starting SSDP...\n");     SSDP.setDeviceType("upnp:rootdevice");     SSDP.setSchemaURL("description.xml");     SSDP.setHTTPPort(80);     SSDP.setName("Philips hue clone");     SSDP.setSerialNumber("001788102201");     SSDP.setURL("index.html");     SSDP.setModelName("Philips hue bridge 2012");     SSDP.setModelNumber("929000226503");     SSDP.setModelURL("http://www.meethue.com");     SSDP.setManufacturer("Royal Philips Electronics");     SSDP.setManufacturerURL("http://www.philips.com");     SSDP.begin();        Serial.printf("Ready!\n");   } else {     Serial.printf("WiFi Failed\n");     while (1) {       delay(100);     }   } }    void loop() {   HTTP.handleClient();   delay(1); } (2)验证上述代码并上传到零知-ESP8266开发板; (3)零知-开发工具中打开串口调试窗口,可以看到如下信息: (4)下面进行测试是否能发现设备: 我们需要下载这个工具:SSDP_Tester. (也可以给我留言,免费传给你) 安装到安卓手机上,然后在SSDP_Tester工具中点击【LISTEN】,可以看到如下信息:   这个设备信息和我们在程序中设置的是一致的:

  • 2019-12-07
  • 发表了主题帖: 【零知ESP8266教程】进阶篇1 WIFI MESH 组网 示例

    前言: 基础篇章中,我们对零知ESP8266的本身的运用大部分局限在基础开发板上的应用,但是,其本身是一个WiFi模块,所以了解和运用它的WiFi功能属于我们的中阶储备。 之后篇章中,我们会穿插基础入门篇,因为各种模块的更新速度和硬件的支持库都在不断的修改适配和调整,相对的我们也会适应现实的要求更新和完善。请大家继续支持零知实验室! 1、引述: MESH组网技术在IOT领域具有非常大的作用,应用非常广泛,主流的无线技术从最开始的Zigbee,到蓝牙,到这里的WIFI都实现了MESH组网技术。在这里使用零知开源平台演示wifi 组网的使用。 2、准备 ①硬件 我们本次只要使用零知-ESP8266; ②软件 软件使用零知开发工具,自带示例: 3、方法步骤 (1)先在零知开发工具中打开HelloMesh示例,或者复制下面的代码到零知开发工具中: /********************************************************** * 文件: x.ino by 零知实验室(www.lingzhilab.com) * -^^- 零知开源,让电子制作变得更简单! -^^- * 时间: 2019/05/28 12:22 * 说明: ************************************************************/ #include <ESP8266WiFi.h> #include <ESP8266WiFiMesh.h> #include <TypeConversionFunctions.h> #include <assert.h> const char exampleMeshName[] PROGMEM = "MeshNode_"; const char exampleWiFiPassword[] PROGMEM = "123456789";//ChangeThisWiFiPassword_TODO unsigned int requestNumber = 0; unsigned int responseNumber = 0; String manageRequest(const String &request, ESP8266WiFiMesh &meshInstance); transmission_status_t manageResponse(const String &response, ESP8266WiFiMesh &meshInstance); void networkFilter(int numberOfNetworks, ESP8266WiFiMesh &meshInstance); /* Create the mesh node object */ ESP8266WiFiMesh meshNode = ESP8266WiFiMesh(manageRequest, manageResponse, networkFilter, FPSTR(exampleWiFiPassword), FPSTR(exampleMeshName), "", true); /** Callback for when other nodes send you a request @param request The request string received from another node in the mesh @param meshInstance The ESP8266WiFiMesh instance that called the function. @returns The string to send back to the other node */ String manageRequest(const String &request, ESP8266WiFiMesh &meshInstance) { // We do not store strings in flash (via F()) in this function. // The reason is that the other node will be waiting for our response, // so keeping the strings in RAM will give a (small) improvement in response time. // Of course, it is advised to adjust this approach based on RAM requirements. /* Print out received message */ Serial.print("Request received: "); Serial.println(request); /* return a string to send back */ return ("Hello world response #" + String(responseNumber++) + " from " + meshInstance.getMeshName() + meshInstance.getNodeID() + "."); } /** Callback for when you get a response from other nodes @param response The response string received from another node in the mesh @param meshInstance The ESP8266WiFiMesh instance that called the function. @returns The status code resulting from the response, as an int */ transmission_status_t manageResponse(const String &response, ESP8266WiFiMesh &meshInstance) { transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE; /* Print out received message */ Serial.print(F("Request sent: ")); Serial.println(meshInstance.getMessage()); Serial.print(F("Response received: ")); Serial.println(response); // Our last request got a response, so time to create a new request. meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + String(F(" from ")) + meshInstance.getMeshName() + meshInstance.getNodeID() + String(F("."))); // (void)meshInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else. return statusCode; } /** Callback used to decide which networks to connect to once a WiFi scan has been completed. @param numberOfNetworks The number of networks found in the WiFi scan. @param meshInstance The ESP8266WiFiMesh instance that called the function. */ void networkFilter(int numberOfNetworks, ESP8266WiFiMesh &meshInstance) { for (int networkIndex = 0; networkIndex < numberOfNetworks; ++networkIndex) { String currentSSID = WiFi.SSID(networkIndex); int meshNameIndex = currentSSID.indexOf(meshInstance.getMeshName()); /* Connect to any _suitable_ APs which contain meshInstance.getMeshName() */ if (meshNameIndex >= 0) { uint64_t targetNodeID = stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length())); if (targetNodeID < stringToUint64(meshInstance.getNodeID())) { ESP8266WiFiMesh::connectionQueue.push_back(NetworkInfo(networkIndex)); } } } } void setup() { // Prevents the flash memory from being worn out, see: https://github.com/esp8266/Arduino/issues/1054 . // This will however delay node WiFi start-up by about 700 ms. The delay is 900 ms if we otherwise would have stored the WiFi network we want to connect to. WiFi.persistent(false); Serial.begin(115200); delay(50); // Wait for Serial. //yield(); // Use this if you don't want to wait for Serial. // The WiFi.disconnect() ensures that the WiFi is working correctly. If this is not done before receiving WiFi connections, // those WiFi connections will take a long time to make or sometimes will not work at all. WiFi.disconnect(); Serial.println(); Serial.println(); Serial.println(F("Note that this library can use static IP:s for the nodes to speed up connection times.\n" "Use the setStaticIP method as shown in this example to enable this.\n" "Ensure that nodes connecting to the same AP have distinct static IP:s.\n" "Also, remember to change the default mesh network password!\n\n")); Serial.println(F("Setting up mesh node...")); /* Initialise the mesh node */ meshNode.begin(); meshNode.activateAP(); // Each AP requires a separate server port. // meshNode.setStaticIP(IPAddress(192, 168, 4, 22)); // Activate static IP mode to speed up connection times. } int32_t timeOfLastScan = -10000; void loop() { if (millis() - timeOfLastScan > 3000 // Give other nodes some time to connect between data transfers. || (WiFi.status() != WL_CONNECTED && millis() - timeOfLastScan > 2000)) { // Scan for networks with two second intervals when not already connected. String request = String(F("Hello world request #")) + String(requestNumber) + String(F(" from ")) + meshNode.getMeshName() + meshNode.getNodeID() + String(F(".")); meshNode.attemptTransmission(request, false); timeOfLastScan = millis(); // One way to check how attemptTransmission worked out if (ESP8266WiFiMesh::latestTransmissionSuccessful()) { Serial.println(F("Transmission successful.")); } // Another way to check how attemptTransmission worked out if (ESP8266WiFiMesh::latestTransmissionOutcomes.empty()) { Serial.println(F("No mesh AP found.")); } else { for (TransmissionResult &transmissionResult : ESP8266WiFiMesh::latestTransmissionOutcomes) { if (transmissionResult.transmissionStatus == TS_TRANSMISSION_FAILED) { Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionResult.SSID); } else if (transmissionResult.transmissionStatus == TS_CONNECTION_FAILED) { Serial.println(String(F("Connection failed to mesh AP ")) + transmissionResult.SSID); } else if (transmissionResult.transmissionStatus == TS_TRANSMISSION_COMPLETE) { // No need to do anything, transmission was successful. } else { Serial.println(String(F("Invalid transmission status for ")) + transmissionResult.SSID + String(F("!"))); assert(F("Invalid transmission status returned from responseHandler!") && false); } } } Serial.println(); } else { /* Accept any incoming connections */ meshNode.acceptRequest(); } } (2)验证并上传上述代码到零知-ESP8266开发板; (3)测试:分别把上述代码上传到两个零知-ESP8266开发板,然后分别连接两个板子的串口调试窗口,然后就可以看到两个节点数据传输信息了:

  • 2019-12-05
  • 发表了主题帖: 【零知esp8266教程】快速入门30 rc-switch无线收发模块的使用

    本实验使用零知esp8266和rc-switch模块的使用。 1、实验材料 零知ESP8266开发板 R433s收、发模块 杜邦线若干 2、连线     3、准备安装 rc-switch软件库,(在百度搜索零知实验室,查看“无线”,便可免费下载) 程序选中rc-switch中的收、发程序即可 安装完成后,便可以使用 4、操作完成后,打开调试窗口,我们就可以看到如下结果了

  • 2019-12-04
  • 发表了主题帖: 【零知ESP8266教程】快速入门29 九轴传感器模块的使用

    本文主要讲述零知ESP8266和MPU-9250的使用,获取得到速度、陀螺仪角度、地磁数据。 1、硬件 零知ESP8266 九轴传感器:MPU-9250 杜邦线: 4条 2、连线 3、代码 (选择示例代码即可) 验证→烧录(上传),打开调试窗口,即可查看效果 4、效果

  • 2019-12-03
  • 发表了主题帖: 【零知ESP8266教程】快速入门28 六轴传感器模块的使用

    本文主要讲述,使用零知ESP8266开发板与六轴传感器(三轴陀螺仪+三轴加速度)的使用 一、硬件 零知ESP8266开发板 六轴传感器:GY-521 杜邦线 4条 二、连接 3、代码 (需要安装 MPU6050软件库,点击这里查看) 安装完成后,选择示例即可 验证→上传,然后打开调试窗口,即可查看效果。 4、效果

  • 发表了主题帖: 【零知ESP8266教程】快速入门27 ADXL345传感器模块的使用

    本文主要讲述,使用零知ESP8266开发板与三轴加速度传感器的使用 一、硬件 零知ESP8266开发板 ADXL345三轴加速度传感器 杜邦线 4条 2、连线 3、程序 (1)(在这里可以先安装一下运行ADXL345所需要的库) 在这里查看安装 PS:安装库时记得选择对应的型号,这里选择零知ESP8266 (2)选择数据库中的示例 验证→上传,打开调试,即可查看效果  

  • 2019-11-15
  • 发表了主题帖: 【零知ESP8266教程】快速入门26 Blynk手机APP显示室内温湿度

    本站分享中小伙伴私信,教程都断了,可以在CSDN查看like-start的同名文章,皆有源码放送,可留言。 本文讲解使用blynk app+服务器(本地) + 零知ESP8266硬件的方法,通过手机APP来观察由ESP8266获取的温湿度信息。 一、硬件 1.电脑,windows系统 2.零知ESP8266开发板 3.智能手机一部 + app(Blynk) 4.micro-usb线 5.SHT30温湿度模块 二、连接     2、关于准备工作不再细讲,请查看 Blynk手机APP点灯示例 ,已经对操作步骤进行了详细说明。 3、手机APP端 我们需要两个组件分别显示温度和湿度信息,做好后界面如下:   准备以下代码: /* Comment this out to disable prints and save space */ #define BLYNK_PRINT Serial #include <ESP8266WiFi.h> #include <BlynkSimpleEsp8266.h> // You should get Auth Token in the Blynk App. // Go to the Project Settings (nut icon). char auth[] = "xx"; // Your WiFi credentials. // Set password to "" for open networks. char ssid[] = "xx"; char pass[] = "xx"; char local_domain[] = "192.168.0.111"; /*SHT3X 传感器 * 使用软I2C接口 */ #define SHT3X_SDA D5 #define SHT3X_SCL D6 #include "SHT3X.h" SlowSoftWire shtWire(SHT3X_SDA,SHT3X_SCL,true); HTU3X myHumidity; BlynkTimer timer; void myTimerEvent() { float humd, temp; myHumidity.readTempAndHumi(&temp, &humd); Serial.print("时间:"); Serial.print(millis()); Serial.print(" 温度:"); Serial.print(temp, 1); Serial.print(" °C"); Serial.print(" 湿度:"); Serial.print(humd, 1); Serial.print("%"); Serial.println(); Blynk.virtualWrite(V0, temp); Blynk.virtualWrite(V1, humd); } void setup() { // Debug console Serial.begin(9600); Blynk.begin(auth, ssid, pass, local_domain,8080); myHumidity.begin(shtWire); timer.setInterval(1000L, myTimerEvent); } void loop() { Blynk.run(); timer.run(); // Initiates BlynkTimer } 更改代码中的IP、token等信息,然后验证并上传到零知-ESP8266板上。 5、验证测试 在手机blynk app上可以观察到如下结果: 更有效果视频可点击查看CSDN!

  • 2019-11-14
  • 发表了主题帖: 【零知ESP8266教程】快速入门25 blynk控制RGB LED

    本文讲解继续使用blynk app+服务器(本地) + 零知ESP8266硬件的方法,通过手机APP控制RGB led三色灯。 一、硬件 1.电脑,windows系统 2.零知ESP8266开发板 3.智能手机一部 + app(Blynk) 4.micro-usb线 5.RGB LED 二、连接 这里的连线:R-D5,G-D6,B-D7,和blynk app里面控件的PIN设置是一一对应的。 三、准备 在这里blynk app和电脑端准备的和这一篇文章的是相同的 软件 (1)app端,使用blynk新建工程,并选择设备未NodeMCU,或ESP8266,然后增加ZERGBA控件,如下: (2)电脑连接的零知ESP8266端如下: /* Comment this out to disable prints and save space */ #define BLYNK_PRINT Serial #include <ESP8266WiFi.h> #include <BlynkSimpleEsp8266.h> // You should get Auth Token in the Blynk App. // Go to the Project Settings (nut icon). char auth[] = "xx"; // Your WiFi credentials. // Set password to "" for open networks. char ssid[] = "xx"; char pass[] = "xx"; char local_domain[] = "192.168.0.111"; void setup() { // Debug console Serial.begin(9600); Blynk.begin(auth, ssid, pass, local_domain,8080); } void loop() { Blynk.run(); } 上面代码中只需要填写自己的TOKEN和wifi热点名字、密码即可。 四、测试验证 (1)在零知开发工具中,可以在串口调试窗口看到如下信息: 表示我们与服务器通信成功的。 (2)在手机blynk上,点击运行按钮后,开始运行,然后就可以控制RGB显示各种颜色了:  

  • 2019-11-08
  • 发表了主题帖: 【零知ESP8266项目篇】1 OLED天气时钟

    引述: 我们一起学了这么久的零知ESP8266的教程,是不是该检验一下自己了呢?在前面的分享中,有小伙伴留言:太简单!那我就顺水推舟,拔高一下,实践搞个小项目——天气时钟。 到现在为止,作为一个基本的开发者,咱们已经对零知ESP8266有了最基本的了解了,可能你早就按耐不住要做项目了吧!那咱今儿个就做个小项目瞧瞧。继续给我们电子世界的轮廓加一个点。 一、硬件准备 电脑,windows系统 零知ESP8266开发板 OLED SSD1306模块 micro-usb线 二、连线     三、软件库 ①打开零知开发工具最新版,选中开发板,如图所示:   ②点击库,然后安装以下两个库,如图: 安装完成后,就可以啦。 四、打开零知开发软件,新建工程,命名weather—station。然后烧写如下代码(已经做好了中文注释,复制粘贴即可): /* 2019年6月13日13:47:26 by 零知实验室 */ #include <ESPWiFi.h> #include <ESPHTTPClient.h> #include <JsonListener.h> // time #include <time.h> #include <sys/time.h> #include <coredecls.h> #include "SSD1306Wire.h" #include "OLEDDisplayUi.h" #include "Wire.h" #include "OpenWeatherMapCurrent.h" #include "OpenWeatherMapForecast.h" #include "WeatherStationFonts.h" #include "WeatherStationImages.h" /*************************** * 开始设置 **************************/ // 这里填写WiFi凭证信息 const char* WIFI_SSID = "WiFi名"; const char* WIFI_PWD = "WiFi密码"; #define TZ 8 // 通用协调时 东八区 北京时间为准 #define DST_MN 60 // 在一些国家依然用夏令时 // Setup const int UPDATE_INTERVAL_SECS = 20 * 60; // 更新20分钟 // 展示设置 const int I2C_DISPLAY_ADDRESS = 0x3c; const int SDA_PIN = D3; const int SDC_PIN = D4; // OpenWeatherMap设置 // 在此处注册以获取API密钥 // https://docs.thingpulse.com/how-tos/openweathermap-key/ //也可以在零知实验室查看原帖获取,或者留言给我呦,免费分享给你 String OPEN_WEATHER_MAP_APP_ID = "3213ac05f30cc2f7d8d8da6d2b03f2e8"; //得到密匙 下面会有教程 /* 转到https://openweathermap.org/find?q=并搜索位置。 通过结果设置并选择最接近要显示的实际位置的条目数据 它将是一个类似于https://openweathermap.org/city/2657896.的链接最后的数字是你分配给下面常量的数字。 */ String OPEN_WEATHER_MAP_LOCATION_ID = "1795565"; //city:深圳 数字指的是openweathermap的分配的ID 同样也有教程 //从此列表中选择语言代码: //阿拉伯文-ar,保加利亚语-bg,加泰罗尼亚语-ca,捷克语-cz,德语-de,希腊语-el, //英语-en,波斯语(波斯语)-fa,芬兰语-fi,法语-fr,加利西亚语-gl, //克罗地亚语-hr,匈牙利语-hu,意大利语-it,日语-ja,韩语-kr, //拉脱维亚-la,立陶宛语-lt,马其顿语-mk,荷兰语-nl,波兰语-pl, //葡萄牙语-pt,罗马尼亚语-ro,俄语-ru,瑞典语-se,斯洛伐克语-sk, //斯洛文尼亚文-sl,西班牙文-es,土耳其文-tr,乌克兰文-ua,越南文-vi, //简体中文-zh_cn,繁体中文-zh_tw。 String OPEN_WEATHER_MAP_LANGUAGE = "zh_cn"; //这里选择中文简体。 const uint8_t MAX_FORECASTS = 4; const boolean IS_METRIC = true; // 根据你的需要调整语言 const String WDAY_NAMES[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; //每周七天 const String MONTH_NAMES[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; //12个月 /*************************** * 结束设置 **************************/ // 初始化OLED地址 // I2C接口:SDA引脚14 SCL引脚12 SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); //为OLED创建一个实例display OLEDDisplayUi ui( &display ); //创建一个ui实例 OpenWeatherMapCurrentData currentWeather; //创建一个当前天气数据 OpenWeatherMapCurrent currentWeatherClient; //创建一个当前天气客户端 OpenWeatherMapForecastData forecasts[MAX_FORECASTS]; OpenWeatherMapForecast forecastClient; #define TZ_MN ((TZ)*60) #define TZ_SEC ((TZ)*3600) #define DST_SEC ((DST_MN)*60) time_t now; // 标记每10分钟更改一次。 bool readyForWeatherUpdate = false; String lastUpdate = "--"; long timeSinceLastWUpdate = 0; //申明原型 void drawProgress(OLEDDisplay *display, int percentage, String label); void updateData(OLEDDisplay *display); void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex); void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state); void setReadyForWeatherUpdate(); //添加框架 //此数组保留指向所有帧的函数指针 //框架是从右向左滑动的单个视图 FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast }; int numberOfFrames = 3; OverlayCallback overlays[] = { drawHeaderOverlay }; int numberOfOverlays = 1; void setup() { Serial.begin(115200); Serial.println(); Serial.println(); // 初始化显示 display.init(); display.clear(); display.display(); //display.flipScreenVertically(); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_CENTER); display.setContrast(255); WiFi.begin(WIFI_SSID, WIFI_PWD); int counter = 0; while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); display.clear(); display.drawString(64, 10, "Connecting to WiFi"); display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole); display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole); display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole); display.display(); counter++; } // 从网络时间服务得到时间 configTime(TZ_SEC, DST_SEC, "pool.ntp.org"); ui.setTargetFPS(30); ui.setActiveSymbol(activeSymbole); ui.setInactiveSymbol(inactiveSymbole); // 你可以改变它, // 向上(TOP), 向左(LEFT), 向下(BOTTOM), 向右(RIGHT) ui.setIndicatorPosition(BOTTOM); // 定义第一个帧位于中间的位置 ui.setIndicatorDirection(LEFT_RIGHT); // 你可以更改幻灯片通过 // 向左滑动(SLIDE_LEFT),向右滑动( SLIDE_RIGHT)向上滑动( SLIDE_TOP), 向下滑动(SLIDE_DOWN) ui.setFrameAnimation(SLIDE_LEFT); //这里填写设置向左滑动,根据上面提供的注释、个人喜好选择 ui.setFrames(frames, numberOfFrames); ui.setOverlays(overlays, numberOfOverlays); // Inital UI takes care of initalising the display too. ui.init(); Serial.println(""); updateData(&display); } void loop() { if (millis() - timeSinceLastWUpdate > (1000L*UPDATE_INTERVAL_SECS)) { setReadyForWeatherUpdate(); timeSinceLastWUpdate = millis(); } if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) { updateData(&display); } int remainingTimeBudget = ui.update(); if (remainingTimeBudget > 0) { //你可以在这里添加一些代码,当然要在下面的remainingTimeBudget(停留时间预算内) //否则会出现闪频状态 delay(remainingTimeBudget); } } void drawProgress(OLEDDisplay *display, int percentage, String label) //绘制进度 { display->clear(); display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_10); display->drawString(64, 10, label); display->drawProgressBar(2, 28, 124, 10, percentage); display->display(); } void updateData(OLEDDisplay *display) //更新数据 { drawProgress(display, 10, "Updating time..."); drawProgress(display, 30, "Updating weather..."); currentWeatherClient.setMetric(IS_METRIC); currentWeatherClient.setLanguage(OPEN_WEATHER_MAP_LANGUAGE); currentWeatherClient.updateCurrentById(&currentWeather, OPEN_WEATHER_MAP_APP_ID, OPEN_WEATHER_MAP_LOCATION_ID); drawProgress(display, 50, "Updating forecasts..."); forecastClient.setMetric(IS_METRIC); forecastClient.setLanguage(OPEN_WEATHER_MAP_LANGUAGE); uint8_t allowedHours[] = {12}; forecastClient.setAllowedHours(allowedHours, sizeof(allowedHours)); forecastClient.updateForecastsById(forecasts, OPEN_WEATHER_MAP_APP_ID, OPEN_WEATHER_MAP_LOCATION_ID, MAX_FORECASTS); readyForWeatherUpdate = false; drawProgress(display, 100, "Done..."); delay(1000); } void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) //绘制数据时间 { now = time(nullptr); struct tm* timeInfo; timeInfo = localtime(&now); char buff[16]; display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_10); String date = WDAY_NAMES[timeInfo->tm_wday]; sprintf_P(buff, PSTR("%s, %02d/%02d/%04d"), WDAY_NAMES[timeInfo->tm_wday].c_str(), timeInfo->tm_mday, timeInfo->tm_mon+1, timeInfo->tm_year + 1900); display->drawString(64 + x, 5 + y, String(buff)); display->setFont(ArialMT_Plain_24); sprintf_P(buff, PSTR("%02d:%02d:%02d"), timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); display->drawString(64 + x, 15 + y, String(buff)); display->setTextAlignment(TEXT_ALIGN_LEFT); } void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) //绘制当前天气信息 { display->setFont(ArialMT_Plain_10); display->setTextAlignment(TEXT_ALIGN_CENTER); display->drawString(64 + x, 38 + y, currentWeather.description); display->setFont(ArialMT_Plain_24); display->setTextAlignment(TEXT_ALIGN_LEFT); String temp = String(currentWeather.temp, 1) + (IS_METRIC ? "°C" : "°F"); display->drawString(60 + x, 5 + y, temp); display->setFont(Meteocons_Plain_36); display->setTextAlignment(TEXT_ALIGN_CENTER); display->drawString(32 + x, 0 + y, currentWeather.iconMeteoCon); } void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) //绘制预测信息 { drawForecastDetails(display, x, y, 0); drawForecastDetails(display, x + 44, y, 1); drawForecastDetails(display, x + 88, y, 2); } void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) //绘制预测明细 { time_t observationTimestamp = forecasts[dayIndex].observationTime; struct tm* timeInfo; timeInfo = localtime(&observationTimestamp); display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_10); display->drawString(x + 20, y, WDAY_NAMES[timeInfo->tm_wday]); display->setFont(Meteocons_Plain_21); display->drawString(x + 20, y + 12, forecasts[dayIndex].iconMeteoCon); String temp = String(forecasts[dayIndex].temp, 0) + (IS_METRIC ? "°C" : "°F"); display->setFont(ArialMT_Plain_10); display->drawString(x + 20, y + 34, temp); display->setTextAlignment(TEXT_ALIGN_LEFT); } void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) //绘制页眉 { now = time(nullptr); struct tm* timeInfo; timeInfo = localtime(&now); char buff[14]; sprintf_P(buff, PSTR("%02d:%02d"), timeInfo->tm_hour, timeInfo->tm_min); display->setColor(WHITE); display->setFont(ArialMT_Plain_10); display->setTextAlignment(TEXT_ALIGN_LEFT); display->drawString(0, 54, String(buff)); display->setTextAlignment(TEXT_ALIGN_RIGHT); String temp = String(currentWeather.temp, 1) + (IS_METRIC ? "°C" : "°F"); display->drawString(128, 54, temp); display->drawHorizontalLine(0, 52, 128); } void setReadyForWeatherUpdate() //设置为天气更新准备 { Serial.println("Setting readyForUpdate to true"); readyForWeatherUpdate = true; } 验证完毕,然后再点击“上传”即可。 代码中获取数据的方法:点击这里 完整工程:weather_station1.7z(若有任何问题,欢迎评论留言) 五、结果   获取返回结果代码:200表示成功了 如果错误码,可以把地址粘贴到浏览器里看看是什么原因。 效果视频:点我拂尘

  • 2019-11-07
  • 发表了主题帖: 【零知ESP8266教程】快速入门23 学以致用OLED

    引述: 现在我们电子世界的轮廓慢慢地显现出来了,但是过于空洞,所以我们需要用一个个的小点来充实这个轮廓,让这个轮廓逐渐成为实心的。这些个点所包含的不光是我们接触的电子产品、软件库、创意、学习经验,更多的是我们从学习电子到创造电子作品这个过程。 前面几次的分享,我们大概了解了OLED的使用,总结一下: 1、模块的引脚使用固定,连线简单。 2、OLED模块参与制作的电子作品需要相关软件库的支持。 跟着这个方法,我们来做一次OLED模块的实践分享。 二维码在我们周围非常常见,如何让二维码呈现在我们的OLED模块上呢? 一、硬件准备 电脑,windows系统 零知ESP8266开发板 OLED SSD1306模块 micro-usb线 二、学习方法的运用 (1)硬件连线 (2)软件库 ESP8266_QRcode Tip:若已经在零知实验室"软件下载"安装了最新的零知开发工具,可以跳过① ②步骤 ①查找: 可以在github网站查找,也可在lingzhilab网站查找。 ②安装: 在零知实验室查找:本地库,即可安装。 (3)打开下载的零知开源软件,选中我们的开发板,如图: 然后查找相关的示例,打开它: 核心代码如下: /* ********************************************************************************* * ESP8266 QRcode * dependency library : * ESP8266 Oled Driver for SSD1306 display by Daniel Eichborn, Fabrice Weinberg * 零知ESP8266-OLED * SDA --> D1-sda * SCL --> D0-scl ***********************************************************************************/ #include <qrcode.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); QRcode qrcode (&display); void setup() { Serial.begin(115200); Serial.println(""); Serial.println("Starting..."); display.begin(SSD1306_SWITCHCAPVCC, 0x3c); display.clearDisplay(); // enable debug qrcode qrcode.debug(); // Initialize QRcode display using library qrcode.init(); // create qrcode qrcode.create("www.lingzhilab.com"); } void loop() { } 三、现在验证代码然后上传到零知-esp8266,可以看到如下结果啦:   用手机QQ扫一扫看看:  

  • 2019-11-06
  • 发表了主题帖: 【零知ESP8266教程】快速入门22 OLED模块的再探索

    引述: 制作完世界时钟之后,最终还是要回归本心。我们发现,和之前的电子作品一样,OLED模块的拓展使用会用到不同相关的软件库,这些软件库的使用是丰富了OLED的实用范围,使得我们制作的电子产品也更加的多样化,在生活中的使用范围也更加广泛。这同时也推动了我们了解电子世界的进程,现在的你,应该对电子世界有一个大概的轮廓了吧。 同理,其他模块的使用也和本次分享的引述一样,拥有更大的发展潜力,这就取决于我们作为开发者的想象力了。 接下来,我们继续分享学习。 本次分享则继续在零知ESP8266上使用OLED,加深我们对OLED模块的认识。 一、硬件 电脑,windows系统 零知ESP8266开发板 OLED SSD1306模块 micro-usb线 二、连线 三、软件库 (1)本次使用了OLED相关的软件库,因此需要安装如下两个库: Tip:如果你的电脑已在零知实验室“软件下载”处安装了最新的零知开发工具,即可跳过此步骤。 1. Adafruit_SSD1306 2. Adafruit-GFX (2)安装 在零知实验室官网搜索:本地库,即可安装。 同时也可以给我留言,我们一起交流学习。 (3)烧录程序 在这里我们选中SSD1306的示例即可。 其完整代码如下: #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>    #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels    // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);    #define NUMFLAKES     10 // Number of snowflakes in the animation example    #define LOGO_HEIGHT   16 #define LOGO_WIDTH    16 static const unsigned char PROGMEM logo_bmp[] = { B00000000, B11000000,   B00000001, B11000000,   B00000001, B11000000,   B00000011, B11100000,   B11110011, B11100000,   B11111110, B11111000,   B01111110, B11111111,   B00110011, B10011111,   B00011111, B11111100,   B00001101, B01110000,   B00011011, B10100000,   B00111111, B11100000,   B00111111, B11110000,   B01111100, B11110000,   B01110000, B01110000,   B00000000, B00110000 };    void setup() {   Serial.begin(9600);        Serial.println("SSD1306 i2c example");      // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally   if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // Address 0x3D for 128x64     Serial.println(F("SSD1306 allocation failed"));     for(;;); // Don't proceed, loop forever   }      // Show initial display buffer contents on the screen --   // the library initializes this with an Adafruit splash screen.   display.display();   delay(2000); // Pause for 2 seconds      // Clear the buffer   display.clearDisplay();      // Draw a single pixel in white   display.drawPixel(10, 10, WHITE);      // Show the display buffer on the screen. You MUST call display() after   // drawing commands to make them visible on screen!   display.display();   delay(2000);   // display.display() is NOT necessary after every single drawing command,   // unless that's what you want...rather, you can batch up a bunch of   // drawing operations and then update the screen all at once by calling   // display.display(). These examples demonstrate both approaches...      testdrawline();      // Draw many lines      testdrawrect();      // Draw rectangles (outlines)      testfillrect();      // Draw rectangles (filled)      testdrawcircle();    // Draw circles (outlines)      testfillcircle();    // Draw circles (filled)      testdrawroundrect(); // Draw rounded rectangles (outlines)      testfillroundrect(); // Draw rounded rectangles (filled)      testdrawtriangle();  // Draw triangles (outlines)      testfilltriangle();  // Draw triangles (filled)      testdrawchar();      // Draw characters of the default font      testdrawstyles();    // Draw 'stylized' characters      testscrolltext();    // Draw scrolling text      testdrawbitmap();    // Draw a small bitmap image      // Invert and restore display, pausing in-between   display.invertDisplay(true);   delay(1000);   display.invertDisplay(false);   delay(1000);      testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps }    void loop() { } (4)验证代码,并且上传 四、结果 效果视频链接:点我拂尘,走起 演示效果极佳,快来动手试试吧!

  • 2019-11-05
  • 发表了主题帖: 【零知ESP8266教程】快速入门21 世界时钟demo

    上次分享了一个本地时钟,小伙伴觉得不fashion,所以思前想后,做一个世界时钟,来撑撑场面,也算是一个小拓展。这次,我们一起制作世界时钟! 一、硬件 电脑,windows系统 零知ESP8266开发板 OLED SSD1306模块 micro-usb线 杜邦线若干 二、连线 三、软件库的查找安装 (1)查找:可以在零知实验室查看“无线”下载安装,也可在github查找安装。 (亦可评论留言,私发给你) OLED和WeatherStation (2)安装:可以在零知实验室搜索:本地库,即可出现安装教程。 (3)安装完成后,打开零知开源软件,选择对应的开发板,如图: (4)我们新建工程,烧写以下代码: #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <Ticker.h> #include <JsonListener.h> #include <SSD1306Wire.h> #include <OLEDDisplayUi.h> #include <Wire.h> #include <WorldClockClient.h> #include "icons.h" #include "fonts.h" /*************************** * Begin Settings **************************/ // WIFI const char* WIFI_SSID = "xx";//在这里写入你的WIFI名字 const char* WIFI_PWD = "xx"; //写WIFI密码 // Setup const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes // Display Settings const int I2C_DISPLAY_ADDRESS = 0x3c; const int SDA_PIN = D3; // const int SDC_PIN = D4; // TimeClient settings // Initialize the oled display for address 0x3c // sda-pin=14 and sdc-pin=12 SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); OLEDDisplayUi ui ( &display ); /*************************** * End Settings **************************/ //String timeZoneIds [] = {"America/New_York", "Europe/London", "Europe/Paris", "Australia/Sydney", ""}; //WorldClockClient worldClockClient("de", "CH", "E, dd. MMMMM yyyy", 4, timeZoneIds); // String timeZoneIds [] = {"America/New_York", "Europe/London", "Europe/Paris", "Australia/Sydney", "Asia/Shanghai"}; WorldClockClient worldClockClient("zh", "CN", "E, dd. MMMMM yyyy", 5, timeZoneIds); // flag changed in the ticker function every 10 minutes bool readyForUpdate = false; String lastUpdate = "--"; Ticker ticker; void updateData(OLEDDisplay *display) { drawProgress(display, 50, "Updating Time..."); worldClockClient.updateTime(); drawProgress(display, 100, "Done..."); readyForUpdate = false; delay(1000); } void drawProgress(OLEDDisplay *display, int percentage, String label) { display->clear(); display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_10); display->drawString(64, 10, label); display->drawProgressBar(10, 28, 108, 12, percentage); display->display(); } void drawClock(OLEDDisplay *display, int x, int y, int timeZoneIndex, String city, const uint8_t* icon) { display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(ArialMT_Plain_10); display->drawString(x + 60, y + 5, city); display->setFont(Crushed_Plain_36); display->drawXbm(x, y, 60, 60, icon); display->drawString(x + 60, y + 15, worldClockClient.getHours(timeZoneIndex) + ":" + worldClockClient.getMinutes(timeZoneIndex)); } void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { drawClock(display, x, y, 0, "New York", new_york_bits); //纽约 } void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { drawClock(display, x, y, 1, "London", london_bits); //伦敦 } void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { drawClock(display, x, y, 2, "Paris", paris_bits); //巴黎 } void drawFrame4(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { drawClock(display, x, y, 3, "Sydney", sydney_bits); //悉尼 } void drawFrame5(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { drawClock(display, x, y, 4, "Beijing", beijing_bits); //北京 } void setReadyForWeatherUpdate() { Serial.println("Setting readyForUpdate to true"); readyForUpdate = true; } // this array keeps function pointers to all frames // frames are the single views that slide from right to left FrameCallback frames[] = { drawFrame1, drawFrame2, drawFrame3, drawFrame4, drawFrame5}; int numberOfFrames = 5; void setup() { Serial.begin(115200); Serial.println(); Serial.println(); // initialize dispaly display.init(); display.clear(); display.display(); //display.flipScreenVertically(); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_CENTER); display.setContrast(255); WiFi.begin(WIFI_SSID, WIFI_PWD); int counter = 0; while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); display.clear(); display.drawString(64, 10, "Connecting to WiFi"); display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbol : inactiveSymbol); display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbol : inactiveSymbol); display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbol : inactiveSymbol); display.display(); counter++; } ui.setTargetFPS(30); // You can change this to // TOP, LEFT, BOTTOM, RIGHT ui.setIndicatorPosition(BOTTOM); // Defines where the first frame is located in the bar. ui.setIndicatorDirection(LEFT_RIGHT); // You can change the transition that is used // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN ui.setFrameAnimation(SLIDE_LEFT); // Add frames ui.setFrames(frames, numberOfFrames); ui.setTimePerFrame(2*1000); // Setup frame display time to 10 sec // Inital UI takes care of initalising the display too. ui.init(); Serial.println(""); updateData(&display); ticker.attach(UPDATE_INTERVAL_SECS, setReadyForWeatherUpdate); } void loop() { if (readyForUpdate && ui.getUiState()->frameState == FIXED) { updateData(&display); } int remainingTimeBudget = ui.update(); if (remainingTimeBudget > 0) { // You can do some work here // Don't do stuff if you are below your // time budget. delay(remainingTimeBudget); } } (5)验证代码,然后上传 四、结果 同时OLED就可以显示世界时钟的效果: 也有视频效果,可以一览哦

  • 回复了主题帖: 【零知ESP8266教程】快速入门20 OLED本地小时钟

    262664916 发表于 2019-11-4 13:51 学习了,谢谢楼主分享
    如果需要相关的资料可以留下邮箱,我把软件库分享给你。谢谢关注哦

  • 2019-11-04
  • 发表了主题帖: 【零知ESP8266教程】快速入门20 OLED本地小时钟

    上次的分享,我们使用NTP获取并且校正了自己的时间。但是远远不够。当你发现一个闹钟已经开始叫不醒贪睡的你时,就会很苦恼。怎么掌控这稍纵即逝的时间呢?简单,拥有第二个时钟表喽。光阴似箭,赶快动手一起制作一个时钟表吧。 本次分享,通过OLED模块显示一个时钟的例子,其次是ESP8266-oled数据库的的使用。话不多说,准备开始: 一、硬件 电脑,windows系统 零知ESP8266开发板 OLED SSD1306模块 micro-usb线 杜邦线若干 二、连线 接线很简单,I2C接口对应连接即可:     三、软件库的查找安装 (1)查找:可以在零知实验室查看无线教程下载安装,也可在github查找安装。 (亦可评论留言,私发给你) esp8266-oled-ssd1306 (2)安装:可以在零知实验室搜索:本地库,即可出现安装教程。 (3)安装完成后,打开零知开源软件,选择对应的开发板,如图: (4)选中之后,就可以看到我们安装软件库出现的示例,如图: (5)验证,然后上传即可 四、结果如图: (标准时间)

  • 2019-11-02
  • 发表了主题帖: 【零知ESP8266教程】快速入门19 使用NTP服务器获取网络时间

    上次的分享,我们获取了一枚天气信息,但是呢,信息最重要的属性之一就是时效性,如何去确认我们信息的时效性呢,简单,保持自己时间的准确喽。 Time is valuable thing! 时间对我们是很重要的。通常,我们需要进行时间校准(PS:在很多时候,你细心留意就发现时间是错误的),一般就可以用NTP服务器进行获取时间信息,下面使用零知-ESP8266上进行NTP时间的获取。 一、硬件 电脑,windows系统 零知ESP8266开发板 micro-usb线 二、 (1)打开零知开源开发软件,选择零知ESP8266开发板,界面如图所示: (2)电脑连接零知ESP8266开发板 (3)烧写程序: ①可以直接选择软件中的示例程序 ②也可以上传以下代码: /*  * TimeNTP_ESP8266WiFi.ino  * Example showing time sync to NTP time source  *  * This sketch uses the ESP8266WiFi library  */    #include <TimeLib.h> #include <ESP8266WiFi.h> #include <WiFiUdp.h>    const char ssid[] = "xx";  //  your network SSID (name) const char pass[] = "xx";       // your network password    // NTP Servers: static const char ntpServerName[] = "cn.ntp.org.cn"; //static const char ntpServerName[] = "time.nist.gov"; //static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov"; //static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov"; //static const char ntpServerName[] = "time-c.timefreq.bldrdoc.gov";    const int timeZone = 8; //BeiJing in China    // const int timeZone = 1;     // Central European Time //const int timeZone = -5;  // Eastern Standard Time (USA) //const int timeZone = -4;  // Eastern Daylight Time (USA) //const int timeZone = -8;  // Pacific Standard Time (USA) //const int timeZone = -7;  // Pacific Daylight Time (USA)       WiFiUDP Udp; unsigned int localPort = 8888;  // local port to listen for UDP packets    time_t getNtpTime(); void digitalClockDisplay(); void printDigits(int digits); void sendNTPpacket(IPAddress &address);    void setup() {   Serial.begin(9600);   while (!Serial) ; // Needed for Leonardo only   delay(250);   Serial.println("TimeNTP Example");   Serial.print("Connecting to ");   Serial.println(ssid);   WiFi.begin(ssid, pass);      while (WiFi.status() != WL_CONNECTED) {     delay(500);     Serial.print(".");   }      Serial.print("IP number assigned by DHCP is ");   Serial.println(WiFi.localIP());   Serial.println("Starting UDP");   Udp.begin(localPort);   Serial.print("Local port: ");   Serial.println(Udp.localPort());   Serial.println("waiting for sync");   setSyncProvider(getNtpTime);   setSyncInterval(300); }    time_t prevDisplay = 0; // when the digital clock was displayed    void loop() {   if (timeStatus() != timeNotSet) {     if (now() != prevDisplay) { //update the display only if time has changed       prevDisplay = now();       digitalClockDisplay();     }   } }    void digitalClockDisplay() {   // digital clock display of the time   Serial.print(hour());   printDigits(minute());   printDigits(second());   Serial.print(" ");   Serial.print(day());   Serial.print(".");   Serial.print(month());   Serial.print(".");   Serial.print(year());   Serial.println(); }    void printDigits(int digits) {   // utility for digital clock display: prints preceding colon and leading 0   Serial.print(":");   if (digits < 10)     Serial.print('0');   Serial.print(digits); }    /*-------- NTP code ----------*/    const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets    time_t getNtpTime() {   IPAddress ntpServerIP; // NTP server's ip address      while (Udp.parsePacket() > 0) ; // discard any previously received packets   Serial.println("Transmit NTP Request");   // get a random server from the pool   WiFi.hostByName(ntpServerName, ntpServerIP);   Serial.print(ntpServerName);   Serial.print(": ");   Serial.println(ntpServerIP);   sendNTPpacket(ntpServerIP);   uint32_t beginWait = millis();   while (millis() - beginWait < 1500) {     int size = Udp.parsePacket();     if (size >= NTP_PACKET_SIZE) {       Serial.println("Receive NTP Response");       Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer       unsigned long secsSince1900;       // convert four bytes starting at location 40 to a long integer       secsSince1900 =  (unsigned long)packetBuffer[40] << 24;       secsSince1900 |= (unsigned long)packetBuffer[41] << 16;       secsSince1900 |= (unsigned long)packetBuffer[42] << 8;       secsSince1900 |= (unsigned long)packetBuffer[43];       return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;     }   }   Serial.println("No NTP Response :-(");   return 0; // return 0 if unable to get the time }    // send an NTP request to the time server at the given address void sendNTPpacket(IPAddress &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(); } 然后验证,并且上传到开发板。 四、结果 然后对照自己的时间: 赶紧动手检查看看自己的时间对不对呢? 我先校准自己的。 顺便问你们一句:有没有发现自己的时间变快了呢?(细思极恐)

  • 2019-10-31
  • 发表了主题帖: 【零知ESP8266教程】快速入门18 ESP8266HTTPClient库 获取天气请求

    上次我们一起学习用ESP8266开发板创建一个热点,即发送射频信号,就像自己的智能手机可以打开热点,使得他人连接,我们智能手机的角色就是向外发送射频信号,然而,用自己的手机去连接WiFi,那手机充当的角色就是接收射频信号的啦。。 同理,零知ESP8266开发板是WiFi模块,既然有发送信号的功能(创建热点),当然也有接收信号的功能。这次的分享我们来让ESP8266开发板接收信息,一起开始实现吧。 一、硬件 电脑,windows系统 零知ESP8266开发板 micro-usb线 二、 (1)软件库: 本示例使用零知-ESP8266来获取天气信息,首先需要安装库: 也可以在GitHub下载,注意要下载5.~版本 (2)解压,然后打开零知开源软件,界面如下: (3)安装到库 也可以解压直接复制到你lingzhi_library存放的位置 这样就完成安装了,届时要记得刷新一下,关闭软件。 三、 重新打开零知开源软件,然后烧录以下代码: /** * Demo: *    演示Http请求天气接口信息 * @author 云上上云 * @date 2019/06/01 */ #include <ESP8266WiFi.h> #include <ArduinoJson.h> #include <ESP8266HTTPClient.h>   //以下三个定义为调试定义 #define DebugBegin(baud_rate)    Serial.begin(baud_rate) #define DebugPrintln(message)    Serial.println(message) #define DebugPrint(message)    Serial.print(message)   const char* AP_SSID     = "**********";         //  **********-- 使用时请修改为当前你的 wifi ssid const char* AP_PSK = "**********";         //  **********-- 使用时请修改为当前你的 wifi 密码 const char* HOST = "http://api.seniverse.com"; const char* APIKEY = "wcmquevztdy1jpca";        //API KEY const char* CITY = "shenzhen"; const char* LANGUAGE = "zh-Hans";//zh-Hans 简体中文  会显示乱码   const unsigned long BAUD_RATE = 115200;                   // serial connection speed const unsigned long HTTP_TIMEOUT = 5000;               // max respone time from server   // 我们要从此网页中提取的数据的类型 struct WeatherData {   char city[16];//城市名称   char weather[32];//天气介绍(多云...)   char temp[16];//温度   char udate[32];//更新时间 };   HTTPClient http; String GetUrl; String response; WeatherData weatherData;   void setup() {   // put your setup code here, to run once:   WiFi.mode(WIFI_STA);     //设置esp8266 工作模式   DebugBegin(BAUD_RATE);   DebugPrint("Connecting to ");//   DebugPrintln(AP_SSID);   WiFi.begin(AP_SSID, AP_PSK);   //连接wifi   WiFi.setAutoConnect(true);   while (WiFi.status() != WL_CONNECTED) {     //这个函数是wifi连接状态,返回wifi链接状态     delay(500);     DebugPrint(".");   }   DebugPrintln("");   DebugPrintln("WiFi connected");   DebugPrintln("IP address: " + WiFi.localIP());     //拼接get请求url    GetUrl = String(HOST) + "/v3/weather/now.json?key=";   GetUrl += APIKEY;   GetUrl += "&location=";   GetUrl += CITY;   GetUrl += "&language=";   GetUrl += LANGUAGE;   //设置超时   http.setTimeout(HTTP_TIMEOUT);   //设置请求url   http.begin(GetUrl);   //以下为设置一些头  其实没什么用 最重要是后端服务器支持   http.setUserAgent("esp8266");//用户代理版本   http.setAuthorization("esp8266","yssy");//用户校验信息 }   void loop() {   //心知天气  发送http  get请求   int httpCode = http.GET();   if (httpCode > 0) {       Serial.printf("[HTTP] GET... code: %d\n", httpCode);       //判断请求是否成功       if (httpCode == HTTP_CODE_OK) {         //读取响应内容         response = http.getString();         DebugPrintln("Get the data from Internet!");         DebugPrintln(response);         //解析响应内容         if (parseUserData(response, &weatherData)) {           //打印响应内容           printUserData(&weatherData);         }       }   } else {       Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());   }   http.end();   delay(1000);//每1s调用一次 }   /** * @desc 解析数据 Json解析 * 数据格式如下: * { *    "results": [ *        { *            "location": { *                "id": "WX4FBXXFKE4F", *                "name": "北京", *                "country": "CN", *                "path": "北京,北京,中国", *                "timezone": "Asia/Shanghai", *                "timezone_offset": "+08:00" *            }, *            "now": { *                "text": "多云", *                "code": "4", *                "temperature": "23" *            }, *            "last_update": "2017-09-13T09:51:00+08:00" *        } *    ] *} */ bool parseUserData(String content, struct WeatherData* weatherData) { //    -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小 //   如果你使用StaticJsonBuffer时才需要 //    const size_t BUFFER_SIZE = 1024; //   在堆栈上分配一个临时内存池 //    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer; //    -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替   DynamicJsonBuffer jsonBuffer;     JsonObject& root = jsonBuffer.parseObject(content);     if (!root.success()) {     DebugPrintln("JSON parsing failed!");     return false;   }     //复制我们感兴趣的字符串   strcpy(weatherData->city, root["results"][0]["location"]["name"]);   strcpy(weatherData->weather, root["results"][0]["now"]["text"]);   strcpy(weatherData->temp, root["results"][0]["now"]["temperature"]);   strcpy(weatherData->udate, root["results"][0]["last_update"]);   //  -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保   //   当你读取字符串时它仍在内存中   return true; }   // 打印从JSON中提取的数据 void printUserData(const struct WeatherData* weatherData) {   DebugPrintln("Print parsed data :");   DebugPrint("City : ");   DebugPrint(weatherData->city);   DebugPrint(", \t");   DebugPrint("Weather : ");   DebugPrint(weatherData->weather);   DebugPrint(",\t");   DebugPrint("Temp : ");   DebugPrint(weatherData->temp);   DebugPrint(" C");   DebugPrint(",\t");   DebugPrint("Last Updata : ");   DebugPrint(weatherData->udate);   DebugPrintln("\r\n"); } 2、验证,上传程序。 四、点击“调试”,就可看到结果啦,如下图:  

  • 发表了主题帖: 【零知ESP8266教程】快速入门17 Station模式 创建一个wifi热点

    上次的分享,我们已经使用软件库扫描到附近的WiFi了,接下来,我们需要使用零知ESP8266WiFi模块创建一个WiFi热点 一、概况 ①Station模式,也叫站点模式; ②Soft-Access Point模式,也叫Soft-AP模式,可以理解为WiFi热点模式; 以上两种的集合模式,Station 兼Soft-Access Point,也是Mesh NetWork的实现基础; 二、下面我们也在我们的零知开源上创建一个连接到可接入点(wifi热点),并且打印station信息。 (1)打开零知开源开发工具 (2)电脑连接ESP8266WIFI模块 (3)烧写以下代码 /** * * statin模式下,创建一个连接到可接入点(wifi热点),并且打印station信息 * @author 云上上云 * @date 2019/06/01 */ #include <ESP8266WiFi.h> #define AP_SSID "**********" //这里改成你的wifi名字 #define AP_PSW "**********" //这里改成你的wifi密码 //以下三个定义为调试定义 #define DebugBegin(baud_rate) Serial.begin(baud_rate) #define DebugPrintln(message) Serial.println(message) #define DebugPrint(message) Serial.print(message) void setup(){ //设置串口波特率,以便打印信息 DebugBegin(115200); //延时2s 为了演示效果 delay(2000); DebugPrintln("Setup start"); //启动STA模式,并连接到wifi网络 WiFi.begin(AP_SSID, AP_PSW); //设置自动连接 WiFi.setAutoConnect(true); //设置自动重连 WiFi.setAutoReconnect(true); DebugPrint(String("Connecting to ")+AP_SSID); //判断网络状态是否连接上,没连接上就延时500ms,并且打出一个点,模拟连接过程 //笔者扩展:加入网络一直都连不上 是否可以做个判断,由你们自己实现 while (WiFi.status() != WL_CONNECTED){ delay(500); DebugPrint("."); } DebugPrintln(""); DebugPrintln("rint Network Info:"); if (WiFi.status() == WL_CONNECTED){ //输出mac地址 DebugPrintln(String("Connected, mac address: ")+WiFi.macAddress().c_str()); //输出station IP地址,这里的IP地址由DHCP分配 DebugPrintln(String("Connected, IP address: ")+WiFi.localIP().toString()); //输出子网掩码地址 DebugPrintln(String("Subnet mask: ")+WiFi.subnetMask().toString()); //输出网关 IP地址 DebugPrintln(String("Gataway IP: ")+WiFi.gatewayIP().toString()); //输出hostname DebugPrintln(String("Default hostname: ")+WiFi.hostname()); //设置新的hostname WiFi.hostname("Station_host_云上上云"); DebugPrintln(String("New hostname: ")+WiFi.hostname()); //输出SSID DebugPrintln(String("SSID: ")+WiFi.SSID()); //输出psk DebugPrintln(String("psk: ")+WiFi.psk()); //输出BSSID DebugPrintln(String("BSSID: ")+WiFi.BSSIDstr()); //输出RSSI DebugPrintln(String("RSSI: ") + WiFi.RSSI() + " dBm"); } DebugPrintln("Setup End"); } void loop() { } (4)验证代码,上传程序,打开调试 三、当连接上WiFi后,结果如下

  • 2019-10-29
  • 发表了主题帖: 【零知ESP8266教程】快速入门16 WiFiScan库的使用 扫描你附近的WiFi

    本帖最后由 roc2 于 2019-10-29 18:19 编辑 上次我们已经学习并分享了零知ESP8266一键配网的操作流程,接下来,我们需要了解ESP8266是怎样找到这些WiFi热点的。 引述:  为了让手机连上一个WiFi热点,基本上都是打开手机设置里面的WiFi设置功能,然后会看到里面有个WiFi热点列表,然后选择连接。 基本上你只要打开手机的WiFi功能,就会发现附近有超级多的各种来路不明的WiFi热点(WiFi有风险,连接需谨慎),那么手机是怎么找得到附近的WiFi的呢?       通常,无线网络提供的WiFi热点,大部分都开放了SSID广播(记得之前博主讲过WiFi热点也可以隐藏的),Scan WiFi的功能就是扫描出所有附近的WiFi热点的SSID信息,这样一来,客户端就可以根据需要选择不同的SSID连入对应的无线网络中。  Scan WiFi库提供了两种方式实现扫描过程: ①同步扫描:通过单个函数在一次运行中完成,需要等待完成所有操作才能继续运行下面的操作。 ②异步扫描:把上面的过程分成几个步骤,每个步骤由一个单独函数完成,我们可以在扫描过程中执行其他任务。 我们的零知ESP8266本身就是WiFi模块,当然也可以扫描到WiFi的热点,接下来,我们一起学习并且找到附近所有的WiFi热点吧。 一、硬件 电脑,windows系统 零知ES8266开发板 micro-usb线 二、软件库 具备ESP8266WiFiScan库。 ESP8266WiFiScan库,大家使用的时候只需要引入,所以要在IDE中安装相应的数据支持库,当然也可以留言,我免费私给你链接! #include<ESP8266WiFi.h> (1)扫描操作方法 ① scanNetworks —— 同步扫描周边有效wifi网络 函数说明: /**  * Start scan WiFi networks available  * @param async         run in async mode(是否启动异步扫描)  * @param show_hidden   show hidden networks(是否扫描隐藏网络)  * @param channel       scan only this channel (0 for all channels)(是否扫描特定通道)  * @param ssid*         scan for only this ssid (NULL for all ssid's)(是否扫描特定的SSID)  * @return Number of discovered networks  */int8_t scanNetworks(bool async = false, bool show_hidden = false, uint8 channel = 0, uint8* ssid = NULL); ② scanNetworks(async ) —— 异步扫描周边有效wifi网络 函数说明: /**  * Start scan WiFi networks available  * @param async         run in async mode(是否启动异步扫描)  * @param show_hidden   show hidden networks(是否扫描隐藏网络)  * @param channel       scan only this channel (0 for all channels)(是否扫描特定通道)  * @param ssid*         scan for only this ssid (NULL for all ssid's)(是否扫描特定的SSID)  * @return Number of discovered networks  */int8_t scanNetworks(bool async = false, bool show_hidden = false, uint8 channel = 0, uint8* ssid = NULL); ③ scanNetworksAsync —— 异步扫描周边wifi网络,并回调结果 函数说明: /**  * Starts scanning WiFi networks available in async mode  * @param onComplete    the event handler executed when the scan is done  * @param show_hidden   show hidden networks   */void scanNetworksAsync(std::function<void(int)> onComplete, bool show_hidden = false); ④ scanComplete —— 检测异步扫描的结果 函数说明: /** * called to get the scan state in Async mode(异步扫描的结果函数)  * @return scan result or status  *          -1 if scan not find  *          -2 if scan not triggered  */ int8_t scanComplete(); ⑤ scanDelete —— 从内存中删掉最近扫描结果 函数说明: /**  * delete last scan result from RAM(从内存中删除最近的扫描结果)  */void scanDelete(); 注意:如果不删除,将会叠加上次扫描的结果; (2)扫描结果方法 ① SSID —— 获取wifi网络名字 函数说明: /**  * Return the SSID discovered during the network scan.  * @param i     specify from which network item want to get the information  * @return       ssid string of the specified item on the networks scanned list  */String SSID(uint8_t networkItem); ② RSSI —— 获取wifi网络信号强度 函数说明: /**  * Return the RSSI of the networks discovered during the scanNetworks(信号强度)  * @param i specify from which network item want to get the information  * @return  signed value of RSSI of the specified item on the networks scanned list  */int32_t RSSI(uint8_t networkItem); ③ encryptionType —— 获取wifi网络加密方式 函数说明: /**  * Return the encryption type of the networks discovered during the scanNetworks(加密方式)  * @param i specify from which network item want to get the information  * @return  encryption type (enum wl_enc_type) of the specified item on the networks scanned list  * ............ Values map to 802.11 encryption suites.....................  *    AUTH_OPEN          ---->     ENC_TYPE_WEP  = 5,  *    AUTH_WEP           ---->     ENC_TYPE_TKIP = 2,  *    AUTH_WPA_PSK       ---->     ENC_TYPE_CCMP = 4,  * ........... except these two, 7 and 8 are reserved in 802.11-2007.......  *    AUTH_WPA2_PSK      ---->     ENC_TYPE_NONE = 7,  *    AUTH_WPA_WPA2_PSK  ---->     ENC_TYPE_AUTO = 8  */uint8_t encryptionType(uint8_t networkItem); ④ BSSID —— 获取wifi网络mac地址 函数说明: /**  * return MAC / BSSID of scanned wifi (物理地址)  * @param i specify from which network item want to get the information  * @return uint8_t * MAC / BSSID of scanned wifi  */uint8_t * BSSID(uint8_t networkItem); /**  * return MAC / BSSID of scanned wifi (物理地址)  * @param i specify from which network item want to get the information  * @return uint8_t * MAC / BSSID of scanned wifi  */String BSSIDstr(uint8_t networkItem); ⑤ getNetworkInfo —— 获取整体网络信息,名字,信号强度等 函数说明: /**  * loads all infos from a scanned wifi in to the ptr parameters  * @param networkItem uint8_t  * @param ssid  const char**  * @param encryptionType uint8_t *  * @param RSSI int32_t *  * @param BSSID uint8_t **  * @param channel int32_t *  * @param isHidden bool *  * @return (true if ok)  */        bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t* &BSSID, int32_t &channel, bool &isHidden); 注意:入参前面多数加了&,意味着调完函数后外面获取到详细信息; ⑥ channel —— 获取wifi网络通道号 函数说明: /**  * return channel of scanned wifi(通道号)  */int32_t channel(uint8_t networkItem); ⑦ isHidden —— 判断wifi网络是否是隐藏网络 函数说明: /**  * return if the scanned wifi is Hidden (no SSID)(判断扫描到的wifi是否是隐藏wifi)  * @param networkItem specify from which network item want to get the information  * @return bool (true == hidden)  */bool isHidden(uint8_t networkItem); 动手操作 多说不宜,实验是检验真理的唯一标准,下面我们就来实际操作一下吧 三、 (1)打开零知开源开发工具,如下图: (2)电脑连接零知ESP8266开发板: (3)输入以下代码,验证,上传 /**  * Demo:  *    STA模式下,演示同步扫描Scan wifi功能  * @author 云上上云  * @date 2019/06/01  */#include <ESP8266WiFi.h>  //以下三个定义为调试定义#define DebugBegin(baud_rate)    Serial.begin(baud_rate)#define DebugPrintln(message)    Serial.println(message)#define DebugPrint(message)    Serial.print(message)  void setup() {  //设置串口波特率,以便打印信息   DebugBegin(115200);  //延时5s 为了演示效果   delay(5000);  // 我不想别人连接我,只想做个站点   WiFi.mode(WIFI_STA);  //断开连接   WiFi.disconnect();   delay(100);   DebugPrintln("Setup done"); } void loop() {   DebugPrintln("scan start");  // 同步扫描,等待返回结果   int n = WiFi.scanNetworks();   DebugPrintln("scan done");  if (n == 0){     DebugPrintln("no networks found");   }else{     DebugPrint(n);     DebugPrintln(" networks found");    for (int i = 0; i < n; ++i){       DebugPrint(i + 1);       DebugPrint(": ");      //打印wifi账号       DebugPrint(WiFi.SSID(i));       DebugPrint(",");       DebugPrint(String("Ch:")+WiFi.channel(i));       DebugPrint(",");       DebugPrint(WiFi.isHidden(i)?"hide":"show");       DebugPrint(" (");      //打印wifi信号强度       DebugPrint(WiFi.RSSI(i));       DebugPrint("dBm");       DebugPrint(")");      //打印wifi加密方式       DebugPrintln((WiFi.encryptionType(i) == ENC_TYPE_NONE)?"open":"*");       delay(10);     }   }   DebugPrintln("");  // 延时5s之后再次扫描   delay(5000); } 四、测试结果(附近潜在的WiFi热点): (我就不一一展示了,它可以扫描完附近所有WiFi)

  • 2019-10-28
  • 发表了主题帖: 【零知ESP8266教程】快速入门15 SmartConfig一键配网

    这可是零知ESP8266的硬核知识哦,因为ESP8266其本身是一个WiFi模块,那么使用它的WiFi功能就是最基本的啦,接下来我们一起研究操作,别走神哦! 首先第一步:配置网络。了解SmartConfig与Airkiss一键配网,给ESP8266一键配网上云端。当你拿到一块WiFi模块,如果需要连上网络,则需要将SSID名称、密码设置到模块当中。 一般有几种方式: ①就是通过串口接到输入设备,通过串口输入AT指令(SSID名称和密码); ②就是设备提供一个AP热点,手机连上这个热点,然后通过手机把家里的WiFi的SSID和密码配置到设备上,最后手机再切换回家里的WiFi,这种配网成功率可以说是100%。 通过SmartConfig技术配置,微信的AirKiss、ESP8266的esptouch,这是最智能的配网方式。但是缺点也很明显,那就是配网成功率未达到100%,同时SmartConfig还得另外安装一个app到你的智能手机。SmartConfig最佳的应用场景就是你开发的产品需要搭配App来使用。 接下来我们通过实例来做一个小DEMO 一、硬件 电脑,windows系统 零知ESP8266开发板 micro-usb线 二、 (1)打开零知开发工具,界面如下:】 (2)电脑连接零知8266WiFi模块   (3)烧入以下代码: /** *          by 零知实验室(www.lingzhilab.com) *    -- 零知开源,让电子制作变得更简单! -- *    作者:云上上云 *    时间: 2019/06/01 13:39 *    说明: 一键配网 **/ #include <ESP8266WiFi.h> void smartConfig() {   WiFi.mode(WIFI_STA);   Serial.println("\r\nWait for Smartconfig等待连接");   delay(2000);   // 等待配网   WiFi.beginSmartConfig();   while (1)   {     Serial.print(".");     delay(500);     if (WiFi.smartConfigDone())     {       Serial.println("SmartConfig Success");       Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());       Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());       WiFi.setAutoConnect(true);  // 设置自动连接       break;     }   }     Serial.println("");   Serial.println("WiFi connected");    Serial.println("IP address: ");   Serial.println(WiFi.localIP()); }   void setup() {   Serial.begin(115200);   smartConfig(); }   void loop() {   delay(100);   Serial.println("配置成功"); } (4)验证代码,连接esp8266,上传程序,打开调试,串口选择1152000,窗口会不断打印一个一个的点,等待连接 三、 然后使用ESP8266提供的App ESPTouch 或者 SmartConfigAPP。(在Github下载,也可至零知实验室官网查看同名原帖下载),进行如下操作:     四、 验证成果,当手机端配置成功,出现如下结果   以上,我们的一键配置就完成了。  

  • 2019-10-26
  • 发表了主题帖: 【零知ESP8266教程】快速入门14-三个IO控制8个LED灯

    在之前我们控制LED的时候,都是一个LED就需要一个对应的引脚。但是在我们开发板引脚有限的情况下,这样使用就很浪费了,我们这里加上一个新元素74HC595模块来实现只用3个IO引脚来控制8个LED。 本次试验中的74HC595实际上就是一个串行输入并行输出的位移缓存器,因此它能使用少量IO来控制多个输出,这在引脚有限的情况下要控制很多LED是非常有用的。 一、工具原料 电脑,windows系统 零知ESP8266开发板 micro-usb线 LED灯红色4个,黄色4个 220Ω 电阻8个 74HC595模块一个 面包板一个+若干跳线 二、硬件连接     三、方法步骤 1、打开零知实验室软件开发工具,如图:   2、然后新建项目,输入以下代码: /** *    文件: 74HC595-8led.ino      by 零知实验室(www.lingzhilab.com) *    -- 零知开源,让电子制作变得更简单! -- *    时间: 2019/05/31 13:39 *    说明: 使用74HC595 模块控制8个led,显示从0-255的二进制编码, **/    int data  = D1;//74HC595的14脚 数据输入引脚SI int clockC = D2;//74hc595的11脚 时钟线 SCK int latch = D4;//74hc595的12脚 输出存储器锁存线RCK    // the setup routine runs once when you press reset: void setup() {     // put your setup code here, to run once:         pinMode(data, OUTPUT);         pinMode(clockC, OUTPUT);         pinMode(latch, OUTPUT);     Serial.begin(9600); }    // the loop routine runs over and over again forever: void loop() {     // put your main code here, to run repeatedly:                    for(int i = 0; i < 256; i++)//一共8位,可以显示0-255的二进制编码         {             Serial.println(i);                            digitalWrite(latch, LOW);//                 shiftOut(data, clockC, MSBFIRST, ~i);//串行数据输出,高位在先                 digitalWrite(latch, HIGH);//锁存                 delay(500);         } } 2、按照之前的方式先【验证】,然后【上传】到开发板中。 四、成果展示 上面步骤成功完成后,我们就可以看到预期的结果了,如下: 效果视频~点我传送噻~拂尘,走

最近访客

< 1/3 >

统计信息

已有25人来访过

  • 芯币:359
  • 好友:--
  • 主题:72
  • 回复:13
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


eric_wang 2019-9-29
roc2: 你你你,为什么转移我的帖子,不服不服,可恶可恶!发发牢骚,,
帖子内嵌推广信息,只能发在信息发布板块。
查看全部