servo_led共用pin

faf4r發表於2024-03-31

舵機和LED使用了同一個GPIO,但他們確實可以正常使用。

原因是引腳只是給出一定脈寬的訊號,而舵機和LED分別對這個訊號做出響應。

20ms的脈衝週期,各自脈寬的表現

  • LED在20ms時熄滅,隨著脈寬減小,越來越亮。

  • 舵機在0.5ms至2.5ms之間工作,其餘部分都不工作

因此只要設定LED亮度時避開舵機工作區間即可。

digitalWrite時LED只能被設定為最亮或熄滅,避開了舵機工作區間。

若使用analogWrite控制LED亮度,同理只要避開舵機區間即可。

程式碼見下:(110行有測試)

#include <ESP8266WiFi.h>
#include <Servo.h>
#include <PubSubClient.h>

//WiFi config
const char* ssid = "Tenda_D7BEA8";
const char* pwd = "********";

//mqtt config
const char* mqtt_broker = "192.168.0.103";
const int mqtt_port = 1883;
const char* topic = "/lock";
WiFiClient espclient;
PubSubClient client(espclient); //必須傳一個client作為引數

//servo config
#define servo_pin 2     //GPIO2--D4 //和燈共用一個pin,但是控制舵機的脈寬只有一小部分。
#define servo_ON 60     //開門的角度
#define servo_OFF 150   //回位的角度
Servo servo;

//LED config
#define led_OFF 199 //200即佔空比100%時不亮,佔空比越低越亮
#define led_ON  100

void setup() {
  analogWriteFreq(50);
  analogWriteRange(200);  //0.1ms

  Serial.begin(115200);
  Serial.println();

  //LED
  analogWrite(LED_BUILTIN, led_ON); //注意LED_BUILTIN也是GPIO2

  //servo
  servo.attach(servo_pin, 500, 2500);
  servo.write(servo_OFF);
  delay(100);

  //wifi
  connect_wifi();

  //mqtt
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);
  connect_mqtt();
  client.subscribe(topic);
}

void loop() {
  client.loop();
}



void connect_wifi() {
  analogWrite(LED_BUILTIN, led_ON);
  Serial.printf("connecting to %s......", ssid);
  WiFi.begin(ssid, pwd);
  while (!WiFi.isConnected()) {
    delay(500);
  }
  Serial.println("connected");
  analogWrite(LED_BUILTIN, led_OFF);
}

void reconnect_wifi() {
  Serial.printf("reconnecting to %s......", ssid);
  analogWrite(LED_BUILTIN, led_ON);
  WiFi.disconnect();  //清楚連線資訊,防止路由器重啟後通道變化
  WiFi.begin(ssid, pwd);
  while (!WiFi.isConnected()) {
    delay(500);
  }
  Serial.println("connected");
  analogWrite(LED_BUILTIN, led_OFF);
  delay(20);
}

void connect_mqtt() {
  analogWrite(LED_BUILTIN, led_ON);
  while (!client.connected()) {
    String client_id = "esp8266-client-" + String(WiFi.macAddress());
    Serial.printf("client %s is connecting to broker %s ... ", client_id.c_str(), mqtt_broker);
    if (client.connect(client_id.c_str())) {
      Serial.println("connected");
      delay(20);
    } else {
      Serial.printf("failed with state %d\n", client.state());
      delay(2000);
    }
  }
  analogWrite(LED_BUILTIN, led_OFF);
  delay(20);
}

void callback(char *topic, uint8_t *payload, unsigned int length) {
  analogWrite(LED_BUILTIN, led_ON);
  String msg = "";
  for (unsigned int i = 0; i < length; i++) {
    msg += (char)payload[i];
  }
  Serial.printf("receive message from topic %s: %s\n", topic, msg.c_str());

  act_on_msg(msg);

  Serial.println("--------------------------");
  // delay(1000);
  // analogWrite(LED_BUILTIN, 5);  //這裡本只想控制燈但是這個脈寬在舵機控制範圍內,所以它被驅動
  analogWrite(LED_BUILTIN, led_OFF);
}

void act_on_msg(String msg) {
  if (msg.equals("open_door")) {
    servo.write(servo_ON);
    delay(2000);
  }
  servo.write(servo_OFF);
  delay(200);
}

相關文章