ESP8266( 多)玩法_esp8266wanfa-程序员宅基地

技术标签: 物联网  单片机  



ESP8266( 多)玩法

本文章中有很多参考,如有侵权,请告知,第一时间删除!
本人第一次写博客,写的不好莫见怪。

一、 基础知识

针脚

针脚与开发板印刷是不一一对应的!!!

这里使用的是nodemuc,其实就是把ESP8266集成了CH340/CP2100 编码烧写器的开发板。好处是所有的针脚都引出来了,更好的拓展性。

另外,针脚的使用也有一点的规则:

引导期间使用的引脚

如果某些引脚被拉低或拉高,则可以防止 ESP8266 启动。 以下列表显示了以下引脚在 BOOT 上的状态:

  • GPIO16: 引脚在 BOOT 时为高电平
  • GPIO0: 如果拉低启动失败
  • GPIO2 :引脚在 BOOT 时为高电平,如果拉低则启动失败
  • GPIO15 :如果拉高则启动失败
  • GPIO3 :引脚在 BOOT 时为高电平
  • GPIO1 : 引脚在 BOOT 时为高电平,如果拉低则启动失败
  • GPIO10 :引脚在 BOOT 时为高电平
  • GPIO9 :引脚在 BOOT 时为高电平

以绿色突出显示的引脚可以使用。 以黄色突出显示的那些可以使用,但您需要注意,因为它们可能主要在启动时出现意外行为。 不建议将红色突出显示的引脚用作输入或输出。

标签 通用输入输出接口 输入 输出 笔记
D0 GPIO16 没有中断 不支持 PWM 或 I2C 开机时高 习惯从深度睡眠中醒来
D1 GPIO5 通常用作 SCL (I2C)
D2 GPIO4 通常用作 SDA (I2C)
D3 GPIO0 拉上来 连接到FLASH按钮,如果拉低启动失败
D4 GPIO2 拉上来 开机时高 连接到板载 LED,如果拉低启动失败
D5 GPIO14 SPI (SCLK)
D6 GPIO12 SPI (味噌)
D7 GPIO13 SPI (MOSI)
D8 GPIO15 拉到地 SPI (CS) 如果拉高启动失败
接收 GPIO3 RX pin 开机时高
TX GPIO1 TX引脚 开机时高 启动时的调试输出,如果拉低启动失败
A0 ADC0 模拟输入 X
引导时引脚为高电平

当 ESP8266 启动时,某些引脚会输出 3.3V 信号。 如果您将继电器或其他外围设备连接到这些 GPIO,这可能会出现问题。 以下 GPIO 在启动时输出高电平信号:

  • GPIO16
  • GPIO3
  • GPIO1
  • GPIO10
  • GPIO9
参考帖子

内存

总的flash只有4MB

nodemcu给程序的容量是1MB,编程时尽量不要超过1MB,这是指编译后的大小,IDE会提示的。

还有3MB左右的data空间,系统固件什么的也在这3MB里。

二、环境配置

  1. 安装Arduino
  2. 安装CH340/CP2100的串口驱动
  3. 查看开发板的串口编号(COM X)
编程环境

ESP8266和nodemuc都没有官方的编程软件,但是可以通过Arduino安装ESP的拓展包来对ESP编程。

拓展–文件—>首选项—>添加网址:http://arduino.esp8266.com/stable/package_esp8266com_index.json

image-20210808164741505image-20210808165113306

然后添加库 工具–>库管理:添加8266的库和需要或者相关的库,没有库编译调用是会报错的。

image-20210808165418769

之后重启IDE即可。。。。。。。

三、玩法

1.控制舵机(物联网开关)

IMG_20210808_165742

这里使用的是D4口(GPIO2),舵机有三根线。

颜色 功能
电源(3–6)V
地 GND
pmw信号

pmw是通过调节一个固定周期为2.5毫秒的方波的占空比来实现转动(舵机的旋转度数)

最简单的控制舵机的代码

#include<Servo.h>            //引用库
Servo myservo;               //创建对象
int dmax,dmin;               //定义旋转角度
void setup(){
  myservo.attach(2,554,2500);//(针脚,方波最小,方波最大)
  }
void loop(){
    myservo.write(dmin);     //旋转最小
    delay(1500);             //延迟1.5s
    myservo.write(dmax);     //旋转最大
    delay(1500);
  }

当然也可以缝合:


//..........................//与其他一样,缝合库,申明什么的
    Servo myservo; 
    myservo.attach(2,554,2500);
    myservo.write(30);
//..........................
//这里是缝合了点灯科技的代码

void button2_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    digitalWrite(5, !digitalRead(5));//*一个普通的控制一个引脚的高低电平,前面还有设置针脚模式的,具 体看官方文档*//
    if(digitalRead(5)==1){          //这里判断针脚电平
      duoji(1);     //转60度
      }
    else if(digitalRead(5)==0){
        duoji(2);  //转回0度
      }
}
void duoji(int d){                    //普通的函数调用
    switch(d){
       case 1:myservo.write(60);break;//转60度
       case 2:myservo.write(0);break; //转回0度
      }
    
    //delay(1500);    
}

这个代码有一个缺陷,就是控制一个IO口的电平,还有舵机PMW信号输出又占用一个IO,对于IO口少的开发板就不是很友好,相当于浪费了一个io,当然也有其他解决方法,比如接个灯泡或者继电器,或者直接编程通过网页让io口直接输出想要的信号,这就涉及到网页http请求了,我也不是很透彻。

这里是完整的代码,修改自己的WiFi和密码阿里云密钥即可:(pmw口是GPIO2)

#define BLINKER_WIFI
#define BLINKER_WITHOUT_SSL
#include <Blinker.h>
#include<Servo.h>

Servo myservo;


char auth[] = "********";//密钥
char ssid[] = "********";//wifi名字
char pswd[] = "********";//密码

// 新建组件对象
BlinkerButton Button1("btn-abc");//板载led
BlinkerButton Button2("btn-2");
BlinkerButton Buttond("btn-d");  //舵机
BlinkerNumber Number1("num-abc");

int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    
}
void button2_callback(const String & state)  
{
    BLINKER_LOG("get button state: ", state);
    digitalWrite(5, !digitalRead(5));
    if(digitalRead(5)==1){
      duoji(1);
      }
    else if(digitalRead(5)==0){
        duoji(2);  
      }
}
void buttond_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
   // digitalWrite(2, !digitalRead(2));
    
}
void duoji(int d){
    switch(d){
       case 1:myservo.write(60);break;
       case 2:myservo.write(0);break;
      }
    
    //delay(1500);    
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

void setup()
{
    // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    BLINKER_DEBUG.debugAll();
    
    // 初始化有LED的IO
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);

    pinMode(5, OUTPUT);
    digitalWrite(5, LOW);

    // 初始化blinker
    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);
    myservo.attach(2,554,2500);
    myservo.write(30);
    Button1.attach(button1_callback);
    Button2.attach(button2_callback);
    Buttond.attach(buttond_callback);
}

void loop() {
  
    Blinker.run();
}

2.led屏幕显示 Hello World

在这里插入图片描述

接口这里使用的是D1(GPIO5), D2(GPIO4),具体接法:**

nodemcu OLED 说明
D1 SCL 串口iis
D2 SDA 串口iis
VCC VCC 电源
GND GND

具体代码:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//库
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
//分辨率
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);                            //初始化屏幕
  display.clearDisplay();                 //清屏

  display.setTextSize(1);                 //显示字号
  display.setTextColor(WHITE);            //颜色
  display.setCursor(0, 10);               //位置
  // Display static text
  display.println("Hello, world!");       //显示文本
  display.display(); 
}

void loop() {
  
}

就是这么简单!具体使用缝合看你的脑袋了。比如很火的wifi时钟粉丝计数器等。。。。。

3.WebServer控制开关

image-20210808175551782

访问esp的ip即可,控制这几个端口的高低电位,接上继电器也是物联网开关。

这里就用到了**http** 协议的 GET 和**POST**了

流程就是–>esp联网–>提供webserver设置变量绑定—>psot/get 变量值—>IO输出–>循环

代码:

别看代码长,其实是添加了HTML代码,CSS代码,JS代码的,使用略微长,也可以调用闪存来存储网页代码。

// Import required libraries
#include "ESP8266WiFi.h"
#include "ESPAsyncWebServer.h"

// Set to true to define Relay as Normally Open (NO)
#define RELAY_NO    true

// Set number of relays
#define NUM_RELAYS  5

// Assign each GPIO to a relay
int relayGPIOs[NUM_RELAYS] = {5, 4, 14, 12, 13};

// Replace with your network credentials
const char* ssid = "";             //wifi
const char* password = "";         //

const char* PARAM_INPUT_1 = "relay";  
const char* PARAM_INPUT_2 = "state";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 3.0rem;}
    p {font-size: 3.0rem;}
    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px} 
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
    input:checked+.slider {background-color: #2196F3}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  %BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
  var xhr = new XMLHttpRequest();
  if(element.checked){ xhr.open("GET", "/update?relay="+element.id+"&state=1", true); }
  else { xhr.open("GET", "/update?relay="+element.id+"&state=0", true); }
  xhr.send();
}</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if(var == "BUTTONPLACEHOLDER"){
    String buttons ="";
    for(int i=1; i<=NUM_RELAYS; i++){
      String relayStateValue = relayState(i);
      buttons+= "<h4>Relay #" + String(i) + " - GPIO " + relayGPIOs[i-1] + "</h4><label class=\"switch\"><input type=\"checkbox\" οnchange=\"toggleCheckbox(this)\" id=\"" + String(i) + "\" "+ relayStateValue +"><span class=\"slider\"></span></label>";
    }
    return buttons;
  }
  return String();
}

String relayState(int numRelay){
  if(RELAY_NO){
    if(digitalRead(relayGPIOs[numRelay-1])){
      return "";
    }
    else {
      return "checked";
    }
  }
  else {
    if(digitalRead(relayGPIOs[numRelay-1])){
      return "checked";
    }
    else {
      return "";
    }
  }
  return "";
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  // Set all relays to off when the program starts - if set to Normally Open (NO), the relay is off when you set the relay to HIGH
  for(int i=1; i<=NUM_RELAYS; i++){
    pinMode(relayGPIOs[i-1], OUTPUT);
    if(RELAY_NO){
      digitalWrite(relayGPIOs[i-1], HIGH);
    }
    else{
      digitalWrite(relayGPIOs[i-1], LOW);
    }
  }
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP8266 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Send a GET request to <ESP_IP>/update?relay=<inputMessage>&state=<inputMessage2>
  server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    String inputMessage2;
    String inputParam2;
    // GET input1 value on <ESP_IP>/update?relay=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1) & request->hasParam(PARAM_INPUT_2)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
      inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
      inputParam2 = PARAM_INPUT_2;
      if(RELAY_NO){
        Serial.print("NO ");
        digitalWrite(relayGPIOs[inputMessage.toInt()-1], !inputMessage2.toInt());
      }
      else{
        Serial.print("NC ");
        digitalWrite(relayGPIOs[inputMessage.toInt()-1], inputMessage2.toInt());
      }
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage + inputMessage2);
    request->send(200, "text/plain", "OK");
  });
  // Start server
  server.begin();
}
  
void loop() {

}

4.WebServer+OLED显示状态

显示当前控制IO口的状态

IMG_20210808_181717

IP 网页

image-20210808182950378

这个代码就是典型的缝合,缝合了oled显示,和webserver控制io口。滑稽!

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

// Load Wi-Fi library
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.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

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Replace with your network credentials

// Replace with your network credentials
const char* ssid     = "";                //WIFI信息
const char* password = "";                //

//String c;
//int a1,a2,a3;
// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output14State = "off";
String output12State = "off";
String output2State = "off";
// Assign output variables to GPIO pins
const int output14 = 14;
const int output12 = 12;
const int output2 = 2;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output14, OUTPUT);
  pinMode(output12, OUTPUT);
  pinMode(output2, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output14, LOW);
  digitalWrite(output12, LOW);
  digitalWrite(output2, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  
  server.begin();
}
void lcddisplay(){

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
   Serial.println(F("SSD1306 allocation failed"));
   for(;;);
  }
  delay(200);
  display.clearDisplay();  
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  //display.printf("%s\n",s);
     if(output2State=="on"&&output14State=="on"&&output12State=="on")
     {//7
     display.printf("G2:ON\nG14:ON\nG12:ON");
     }
     else if(output2State=="off"&&output14State=="off"&&output12State=="off")
     {//0
     display.printf("G2:OFF\nG14:OFF\nG12:OFF");
     }
     else if(output2State=="off"&&output14State=="off"&&output12State=="on")
     {//1
     display.printf("G2:OFF\nG14:OFF\nG12:ON");
     }
     else if(output2State=="off"&&output14State=="on"&&output12State=="off")
     {//2
     display.printf("G2:OFF\nG14:ON\nG12:OFF");
     }
     else if(output2State=="off"&&output14State=="on"&&output12State=="on")
     {//3
     display.printf("G2:OFF\nG14:ON\nG12:ON");
     }
     else if(output2State=="on"&&output14State=="off"&&output12State=="off")
     {//4
     display.printf("G2:ON\nG14:OFF\nG12:OFF");
     }
     else if(output2State=="on"&&output14State=="off"&&output12State=="on")
     {//5
     display.printf("G2:ON\nG14:OFF\nG12:ON");
     }
     else if(output2State=="on"&&output14State=="on"&&output12State=="off")
     {//6
     display.printf("G2:ON\nG14:ON\nG12:OFF");
     }
  
  display.display();
 
  }
void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    currentTime = millis();
    previousTime = currentTime;
    while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
      currentTime = millis();         
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /2/on") >= 0)
            {
              Serial.println("GPIO 2 on");
              output2State = "on";
              //a1=1;
              digitalWrite(output2, HIGH);
            } 
             else if (header.indexOf("GET /2/off") >= 0)
            {
              Serial.println("GPIO 2 off");
              output2State = "off";
              //a1=0;
              digitalWrite(output2, LOW);
            }
              else if (header.indexOf("GET /14/on") >= 0) 
            {
              Serial.println("GPIO 14 on");
              output14State = "on";
              //a2=1;
              digitalWrite(output14, HIGH);
            } 
              else if (header.indexOf("GET /14/off") >= 0)
            {
              Serial.println("GPIO 14 off");
              output14State = "off";
              //a2=0;
              digitalWrite(output14, LOW);
            } 
              else if (header.indexOf("GET /12/on") >= 0) 
            {
              Serial.println("GPIO 12 on");
              output12State = "on";
             // a3=1;
              digitalWrite(output12, HIGH);
            } 
              else if (header.indexOf("GET /12/off") >= 0)
            {
              Serial.println("GPIO 12 off");
              output12State = "off";
              //a3=0;
              digitalWrite(output12, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 2  
            client.println("<p>GPIO 2 - State " + output2State + "</p>");
            // If the output2State is off, it displays the ON button       
            if (output2State=="off") {
              client.println("<p><a href=\"/2/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/2/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
            
            // Display current state, and ON/OFF buttons for GPIO 14  
            client.println("<p>GPIO 14 - State " + output14State + "</p>");
            // If the output14State is off, it displays the ON button       
            if (output14State=="off") {
              client.println("<p><a href=\"/14/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/14/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 12  
            client.println("<p>GPIO 12 - State " + output12State + "</p>");
            // If the output12State is off, it displays the ON button       
            if (output12State=="off") {
              client.println("<p><a href=\"/12/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/12/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    lcddisplay();
    // Close the connection
    
    client.stop();
    
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

5.传感器获取(DHT11)

还没到。。。。待续。。。。

6.WiFi时钟

也还没到。。。。待续。。。。

待续

参考论坛

我很多的代码都是参考这里然后缝合的,说抄的都行。。。。。(手动滑稽)

点击这里

https://randomnerdtutorials.com/projects-esp8266/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_56699630/article/details/119518806

智能推荐

【jupyter notebook 】使用【pyecharts】做数据分析时不显示图片-程序员宅基地

文章浏览阅读1.6k次。jupyter notebook 使用pyecharts做数据分析时不显示图片解决方法:退出当前笔记,再次进入运行(就像电脑重启可以解决80%的问题)jupyter notebook 运行py文件%load XX.py 是加载后运行;%run XX.py是不加载运行...

STM32+ESP8266+MQTT协议上传云平台(OneNET)_esp8266 mqtt 图片传输 stm32-程序员宅基地

文章浏览阅读6.7k次,点赞5次,收藏59次。STM32+ESP8266+MQTT协议上传云平台(OneNET)_esp8266 mqtt 图片传输 stm32

用工作流思想实现简单的校园请假系统_用业务流程图表示学生上课请假流程(可与考勤流程合并)-程序员宅基地

文章浏览阅读4.5k次,点赞10次,收藏28次。写在前面这两周软件工程课留了一个作业,要写一个小程序去体现工作流,具体内容不限。我上周也写过一篇《浅谈对于工作流的认知》这篇博客给冯冯。但是那时候对于工作流的认识可能连皮毛都没有,里面也有很多错误和表述不清楚的地方。为了弥补上周的错误,我重新写一篇。这次的认识也算是得到的老师的认可,所以我觉得我现在对于工作流的认识也更加靠谱。我对于工作流的认识和程序的设计灵感来源于:老师讲课的内容、OY的程序、FF的数据库设计、姐姐给的资料和第一周被老师骂的同学们。程序设计对于理论知识大家可以上网查,这里就不整理了。_用业务流程图表示学生上课请假流程(可与考勤流程合并)

vim 安装vim-go 打造GOLANG 专用IDE_vim安装golang插件-程序员宅基地

文章浏览阅读1.1w次。分两步:第一步:安装vim插件管理器第二步:安装vim-go插件。---------------------------------------------------------------------------------------开始:第一步:安装Vundle根据Vundle的安装说明,首先安装Vundle:$ git clone https://gi_vim安装golang插件

(转)CSS结合伪类实现icon_纯css3伪类实现icon标签效果-程序员宅基地

文章浏览阅读1.2k次。老规矩,还是先说说业务场景:有一个图片列表,可以添加、删除和更改,其中呢删除时设计给的设计稿时悬浮(hover)在图片上时显示删除的图标,所以就有了这个用before实现icon的场景。_纯css3伪类实现icon标签效果

php用QueryList异步爬取网页数据_querylist::get-程序员宅基地

文章浏览阅读992次。环境要求PHP >= 7.0如果你的PHP版本还停留在PHP5,或者不会使用Composer,你可以选择使用QueryList3,QueryList3支持php5.3以及手动安装。 QueryList3 档:http://v3.querylist.cc安装通过Composer安装:composer require jaeger/querylist使用元素操作1.采集「昵图网..._querylist::get

随便推点

命令格式化CMD_cmd 格式化盘符-程序员宅基地

文章浏览阅读1.5k次。_cmd 格式化盘符

Tip和菜单的实现方式-程序员宅基地

文章浏览阅读133次。Tip和菜单有类似的功能,即鼠标光标移上去的时候显示指定元素,鼠标光标离开的时候隐藏该元素。如下 示例1:下拉菜单(鼠标移动到“客户服务”上时出现,离开则隐藏) 示例2:水平菜单(鼠标移动到“餐饮美食”出现,离开则隐藏) 示例3:Tip示例(鼠标移动到“更换”出现,离开则隐藏) 从交互角度讲很简单,移上去显示,离开隐藏。代码则是两个事件mousee..._center和tip方式

Hash算法解决冲突的方法一般有以下几种常用的解决方法_解决希尔冲突的方法-程序员宅基地

文章浏览阅读1.3w次,点赞7次,收藏16次。Hash算法解决冲突的方法一般有以下几种常用的解决方法 1, 开放定址法: 所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入 公式为:fi(key) = (f(key)+di) MOD m (di=1,2,3,……,m-1) ※ 用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列_解决希尔冲突的方法

【福大/计院】转专业_福州大学转计算机专业考试内容-程序员宅基地

文章浏览阅读4.7k次,点赞20次,收藏58次。fzu计院转专业经验帖,目前记录有18-22年近五年题型情况以供参考。_福州大学转计算机专业考试内容

java 字符串从后向前_Java String字符串总结-程序员宅基地

文章浏览阅读2.5k次。前面我们总结了数组操作,这里我们将总结字符串相关的知识,除了总结String的API用法,同时我们还会总结一些相关的知识点,包括字符串常量池、StringBuffer、StringBuilder,以及equals和==的用法。一、String的用法String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象。java把String类声明的final类,不...

retrofit2设置超时,Retrofit2 SocketTimeOutException-程序员宅基地

文章浏览阅读695次。I setup for Retrofit:private Interceptor interceptor = new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();if (!NetworkUtil.isNetwo..._retrofit2 timeout