五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

基于ESP32開發(fā)智能物聯(lián)網(wǎng)微型設備

2023-03-14 16:15 作者:jack-001  | 我要投稿

介紹

Picoclick 是一種微型設備,可用作物聯(lián)網(wǎng)按鈕。它是一種一鍵式設備,可讓您控制智能家居或物聯(lián)網(wǎng)中的不同內(nèi)容。一個基本示例是通過按下按鈕來切換燈泡。此外,Picoclick-C3 可以用作迷你開發(fā)板,因為它帶有 FPC 擴展端口,可以連接其他硬件。


用例

該設備能夠連接到 WiFi 網(wǎng)絡并執(zhí)行任務,例如發(fā)送消息或?qū)懭胫黝} (MQTT)。與接入點的連接設置需要一些時間(大約 2-3 秒),這對某些應用程序來說太長了——至少對我來說是這樣。因此,我總是將我的 Picoclicks 與 ESPNOW 一起使用,ESPNOW 是 Espressif 自己開發(fā)的 WiFi 協(xié)議。它不需要連接到接入點,因此通信速度超快。然而,當使用 ESPNOW 協(xié)議時,需要有一個橋接器(基于 ESP 的設備)將這些消息轉(zhuǎn)換為例如 MQTT 消息。

工作原理

Picoclick 是一款超低功耗設備 - 它可以通過軟件關(guān)閉自己的電源,并且在不活動時僅消耗約 2μA(這僅歸功于嵌入式電池保護)。所謂的電源鎖存電路能夠管理穩(wěn)壓器的啟用。這可以通過兩種方式完成:

  • 按鈕。當按下按鈕時,電壓調(diào)節(jié)器將被啟用,因此設備將被激活。

  • 閂鎖。GPIO 或處理器的任何其他輸出。

對于以前版本的 Picoclick,我選擇了處理器的普通 GPIO。按下按鈕時,處理器將啟動,其首要任務是觸發(fā)鎖存器,該鎖存器將保持設備的電源。如果設備應該關(guān)閉,鎖存器可以接地并且電源將被禁用。這確保了處理器足夠快來觸發(fā)鎖存器——否則設備將在沒有任何操作的情況下關(guān)閉。

這是 Picoclick-C3 的黃金點。它不使用 GPIO 作為鎖存器,而是使用嵌入式閃存的電源信號。關(guān)于 ESP32-C3 的數(shù)據(jù)表,在處理器深度睡眠期間電源將被停用以節(jié)省一些電量。此外,該電源將在處理器通電后立即出現(xiàn)。因此,要停用 Picoclick 設備,只需進入深度睡眠模式即可。(可以肯定的是:設備不會進入深度睡眠模式,因為它會預先斷電)

除此之外,您不必為軟件中的閂鎖而煩惱,也不必將 ESP32-C3 配置得盡可能快(如 C3T)。因此不再需要使用 ESP-IDF 來刷寫 Picoclick。Arduino 框架也將與該設備完美配合。

?

?

?

?

?

概述

顧名思義,Picoclick-C3 基于 ESP32-C3,這是一款運行頻率高達 160MHz 的 32 位 RISC-V 處理器。

特征

·??????? Picoc尺寸:18x22mm

·??????? 單片機:ESP32-C3FH4

·??????? 單按鈕界面

·??????? 兩個 APA102-2020 RGB LED

·??????? 嵌入式電池保護

·??????? 帶狀態(tài) LED 的嵌入式電池充電

·??????? 優(yōu)化的電池監(jiān)控

·??????? 帶有兩個 GPIO 和電源引腳的擴展端口

·??????? 超低功耗設備

·??????? 包括一個板載芯片天線


正面

正面主要只有三樣東西:12mm 按鈕、兩個 APA102-2020 LED 和 6p FPC 連接器。此外還有兩個焊接跳線。




?

背面

背面是主要部件面。它擁有USB Type-C接口、ESP32-C3、電池充電以及電池保護電路、穩(wěn)壓器、天線及其匹配網(wǎng)絡和電源鎖存電路。

功能? ? ? ? ? ? ? ? ? ? ? ? ? ??GPIO ESP32-C3? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?備注

APA102 ? SDI (LED)? ? ? ? ? ? ? ? ? ? ? ?通用輸入輸出口7? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸出

APA102 時鐘 (LED)? ? ? ? ? ? ? ? ? ? ? ??通用輸入輸出口6? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? 輸出

按鈕狀態(tài)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?通用輸入輸出口5? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸入

電池電壓? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?通用輸入輸出口4? ? ? ? ? ? ? ? ? ? 輸入,包括一個 1:1 分壓器

電池電壓觸發(fā)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?通用輸入輸出口3? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸出

電池連接

電池連接


目前的功耗

下面所有的電流消耗都是測得的。

模式? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??平均電流? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?備注

WiFi已激活? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 74毫安? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?峰值可達 200mA

WiFi 禁用且 LED 燈變暗? ? ? ? ? ? ? ? ? ? ? ? ?27毫安

Picoclick 已停用? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2微安

可以通過以下步驟降低活動模式下的電流消耗:

·??????? 僅在真正需要時才打開 WiFi。

·??????? 降低 CPU 頻率。使用嵌入式時鐘 (40MHz),您可以將頻率設置為 10、20 和 40MHz。10MHz 僅適用于 LED 應用。

·??????? 降低 APA102 LED 亮度。

跳線

有兩個具有兩種不同功能的焊接跳線。BOOT和USB跳線。


引導跳線

左側(cè)跳線將 MCU 的引導引腳連接到 GND,從而強制進入 ESP32 的引導模式。

USB 跳線

右邊的跳線將 USB 電壓連接到電池電壓,這樣 Picoclick 就可以直接通過 USB 端口供電,而無需連接另一個電源。那時(當然)不使用電池充電器。

備注?。?/strong>如果此跳線閉合,請勿將電池連接到 Picoclick,否則會毀壞 Picoclick、您的電池或兩者。

?

?


?

軟 ?件

重要的提示

Picoclick 的典型過程如下所示:

1.?? 1. 按下按鈕將激活 Picoclick。

2.?? 2.將發(fā)送一條消息。

3.?? 3.一些 LED 的東西會發(fā)生。

4.?? 4.Picoclick 將自行停用。

根據(jù)使用情況和/或所使用的協(xié)議,可以或多或少地快速處理這四個步驟。例如,如果使用 ESP-NOW,可以在 500 毫秒內(nèi)到達第 4 點。

如果您想將新代碼上傳到 Picoclick,那么激活設備很重要。這聽起來很簡單,但如果設備只激活了幾百毫秒,那么您可能不會在正確的時間點開始上傳過程。即使按住按鈕的時間更長,一旦 MCU 進入深度睡眠模式,嵌入式閃存的電源也會被停用。

為了有足夠的時間上傳新代碼,建議在進入深度睡眠模式之前使用循環(huán)。這個循環(huán)看起來像這樣:

int counter = 0;

while(digitalRead(BUTTON_PIN) == 1){

??? leds[0] = counter % 2 == 0 ? CRGB::Blue : CRGB::Black;

??? leds[1] = (counter+1) % 2 == 0 ? CRGB::Blue : CRGB::Black;

??? FastLED.show();

??? delay(50);

??? counter++;

}

?

// 添加一個循環(huán),只要按下按鈕就會等待進入深度睡眠。

// 一旦進入深度睡眠,USB 控制臺就不再可用。

esp_deep_sleep_start();

}

?

因此只要按下按鈕,設備就會交替閃爍兩個 LED。此后將進入深度睡眠模式。

如果您沒有遵循這些說明并且無法將代碼閃存到您的 Picoclick,那么您必須按照下一章中的步驟進行操作。

引導跳線

Boot soldering jumper將ESP32的boot strapping pin連接到GND,再次上電即進入boot模式。

需要引導焊接跳線的原因:

·??????? 您的代碼進入深度睡眠模式的速度太快(如上所述)

·??????? 您不小心上傳了錯誤的代碼(例如)切換 GPIO9

·??????? 您的刷機過程在上傳過程中崩潰

如果發(fā)生上述情況,那么您必須像這樣進行:

1.?? 切斷電源。如果您通過 USB 或擴展端口為 Picoclick 供電,則只需拔下它即可;如果你用電池供電,你必須拆焊它(至少一個連接)

2.?? 焊接或短接 PCB 按鈕側(cè)的引導跳線。

3.?? 連接電源(建議使用 USB 或擴展端口,否則必須再次拆焊電池)。

4.?? 如果在最后一步中尚未完成,請將 Picoclick 連接到您的計算機。

5.?? 按下 Picoclick 的按鈕并點擊 PlatformIO 中的上傳按鈕。

6.?? 如果完成,斷開所有電源。

7.?? 拆焊引導跳線。

8.?? 連接你的最終電源(這里是可以再次連接電池的地方)。

?

?

獲取電池電壓

Picoclick-C3 具有優(yōu)化的電池監(jiān)控功能,在不使用時不會消耗任何電量。作為比較:即使 Picoclick 未處于活動狀態(tài),C3T 也需要大約 3μA 的電流。

要讀取電池電壓,您必須將狀態(tài)ADC_ENABLE_PIN從高變?yōu)榈停缓罂梢宰x取幾毫秒的電壓。讀取電池電壓后,返回該引腳的高電平狀態(tài)以便之后再次讀取電壓是有用的。

下面的函數(shù)讀取 ADC 連接到的模擬引腳,并返回過濾后的(100 除以 100 的總和)電池電壓(以伏特為單位)。在最后一行代碼中,原始模擬值將使用乘法器轉(zhuǎn)換為電壓值。如果需要,也可以添加恒定的線性偏移。

#define BAT_VOLT_MULTIPLIER?? 1.43

#define BAT_VOLT_OFFSET?????? 0

?

float get_battery_voltage(){

? digitalWrite(ADC_ENABLE_PIN, LOW);

? delayMicroseconds(10);

? int sum = 0;

? for(int i=0; i<100; i++){

??? sum = sum + analogRead(ADC_PIN);

? }

? float result = sum/100.0;

? digitalWrite(ADC_ENABLE_PIN, HIGH);

? return float(result) * BAT_VOLT_MULTIPLIER + BAT_VOLT_OFFSET;

}

串行輸出

Picoclick 沒有標準串行控制臺,因為它使用 USB-CDC 接口與處理器通信。使用 寫入標準控制臺Serial.print("...")會將數(shù)據(jù)輸出到未連接到 Picoclick 的 UART 接口。

盡管如此,仍然有一種方法可以使用串行控制臺。這就像使用printf("...")instead of 一樣簡單Serial.print("...")。此外,串行控制臺不需要使用Serial.begin(X).

將 Picoclick 的電池電壓寫入串行控制臺的基本示例:

#include <Arduino.h>

#include <WiFi.h>

#include "config.h"

?

void setup(){

? pinMode(BUTTON_PIN, INPUT);

? pinMode(ADC_ENABLE_PIN, OUTPUT);

? pinMode(ADC_PIN, INPUT);

? analogReadResolution(12);

? digitalWrite(ADC_ENABLE_PIN, HIGH);

?

? btStop();

? WiFi.mode(WIFI_OFF);

?

? FastLED.addLeds<APA102, APA102_SDI_PIN, APA102_CLK_PIN, BGR>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

? FastLED.setBrightness(160);

? delay(50);

?

? set_fastled(CRGB::Blue);

?

? printf("Setup done!\r\n");

}

?

void loop() {

? printf("Battery voltage: %i mV\r\n", int(get_battery_voltage()));

? delay(500);

}

請確保不要忘記將回車符 ( \r) 和換行符 ( \n) 添加到字符串的末尾。

要在 PlatformIO 中打開串行監(jiān)視器,您必須按下左下角帶有電源適配器的按鈕。

?

ESP-NOW

ESP -NOW是低延遲應用程序的絕佳協(xié)議,因為無接入點通信可實現(xiàn)超快速消息傳輸。按下按鈕和接收發(fā)送消息之間的延遲低至 200 毫秒。這非常適合智能家居解決方案,您可以立即看到結(jié)果(燈/插座亮起)。

將 ESP-NOW 與 Picoclicks 一起使用時,您必須使用基于 ESP 的橋?qū)⑦@些消息轉(zhuǎn)換為另一種協(xié)議的消息。在大多數(shù)情況下,ESP-NOW 到 MQTT 橋是最好的選擇。在討論網(wǎng)橋之前,讓我們先看看發(fā)送者代碼。

ESP-NOW發(fā)送器

在這里,發(fā)送者是物聯(lián)網(wǎng)按鈕本身。一旦按下 Picoclick,一條消息將充滿信息并發(fā)送到其目的地。之后 Picoclick 將再次停用。功能代碼可能如下所示:

#include <Arduino.h>

#include <WiFi.h>

#include <esp_now.h>

#include <FastLED.h>

#include "config.h"

?

// ESPNOW packet structure.

// Can be modified but should be the same on the receivers side.

typedef struct struct_message {

? int id;

? int value;

? int battery_level;

? int single_tap_duration;

} struct_message;

?

typedef struct struct_message_recv {

??? bool answer;

} struct_message_recv;

?

struct_message data;

struct_message_recv data_recv;

?

#define ESPNOW_ID 8888 // Random 4 digit number

uint8_t receiver_address[] = {0x10, 0x91, 0xA8, 0x32, 0x7B, 0x70}; // Mac address of the receiver.

?

bool espnow_answer_received = false;

?

void on_data_recv(const uint8_t * mac, const uint8_t *incomingData, int len) {

? memcpy(&data_recv, incomingData, sizeof(data_recv));

? espnow_answer_received = true;

}

?

void setup(){

? pinMode(BUTTON_PIN, INPUT);

? pinMode(ADC_ENABLE_PIN, OUTPUT);

? pinMode(ADC_PIN, INPUT);

? analogReadResolution(12);

? digitalWrite(ADC_ENABLE_PIN, HIGH);

?

? btStop();

? WiFi.mode(WIFI_STA);

?

? FastLED.addLeds<APA102, APA102_SDI_PIN, APA102_CLK_PIN, BGR>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

? FastLED.setBrightness(160);

? delay(50);

?

? if(esp_now_init() != ESP_OK) {

??? printf("Error initializing ESP-NOW\r\n");

??? return;

? }

?

? set_fastled(CRGB::Blue);

?

? esp_now_peer_info_t peerInfo;

?

? memcpy(peerInfo.peer_addr, receiver_address, 6);

? peerInfo.channel = 0;?

? peerInfo.encrypt = false;

?????

? if(esp_now_add_peer(&peerInfo) != ESP_OK){

??? printf("Failed to add peer\r\n");

??? return;

? }

?

? esp_now_register_recv_cb(on_data_recv);

?

? // Fill ESPNOW struct with values.

? data.id = ESPNOW_ID;

? data.value = 1;

? data.battery_level = int(get_battery_voltage());

? data.single_tap_duration = 1000;

?

? esp_now_send(receiver_address, (uint8_t *) &data, sizeof(data));

?

? // wait on espnow answer

? unsigned long t_wait_answer_start = millis();

? while(!espnow_answer_received && millis() <= t_wait_answer_start + 300){

??? delayMicroseconds(1);

? }

?

? // This will reduce power consumption.

? WiFi.mode(WIFI_OFF);

? setCpuFrequencyMhz(10);

?

? CRGB col = espnow_answer_received ? CRGB::Green : CRGB::Red;

? set_fastled(col);

? delay(500);

?

? int counter = 0;

? while(digitalRead(BUTTON_PIN) == 1){

??? set_fastled(counter % 2 == 0 ? CRGB::Blue : CRGB::Black, (counter+1) % 2 == 0 ? CRGB::Blue : CRGB::Black);

??? delay(50);

??? counter++;

? }

?

? set_fastled(CRGB::Blue);

? delay(500);

?

? // Add a loop which will wait as long as the button is pressed before entering deepsleep.

? // Once in deepsleep the USB console is not available anymore.

? esp_deep_sleep_start();

}

?

void loop() {

?

}

上面的代碼還做了一件事,確保消息傳遞成功。在它發(fā)出包含所有信息的初始消息后,它等待接收設備的應答 300 毫秒:

while(!espnow_answer_received && millis() <= t_wait_answer_start + 300){

??? delayMicroseconds(1);

}

如果執(zhí)行接收回調(diào),則該espnow_answer_received標志將設置為true,因此一旦發(fā)送方收到消息。如果不是這種情況,則 while 循環(huán)將在 300 毫秒后退出。為了向用戶提供反饋,LED 將根據(jù)接收狀態(tài)呈綠色或紅色亮起。

CRGB col = espnow_answer_received ? CRGB::Green : CRGB::Red;

ESP-NOW 接收器

接收器可以是任何基于 ESP 的設備,但在這種情況下,我也使用 Picoclick。按下按鈕后,接收器將開機并等待來自發(fā)送器的消息。在等待期間,LED 將循環(huán)顯示所有顏色。

收到消息后,send_answer()將調(diào)用該函數(shù)。它使用接收到的發(fā)送方設備的 MAC 地址添加 ESP-NOW 對等點,發(fā)送應答消息,然后刪除對等點。

當接收器設備像發(fā)送器一樣將其 LED 變?yōu)榫G色時,兩個設備將幾乎同時亮起綠色。

#include <Arduino.h>

#include <WiFi.h>

#include <esp_now.h>

#include <FastLED.h>

#include "config.h"

?

// ESPNOW packet structure.

// Can be modified but should be the same on the receivers side.

typedef struct struct_message {

? int id;

? int value;

? int battery_level;

? int single_tap_duration;

} struct_message;

?

typedef struct struct_message_recv {

??? bool answer;

} struct_message_recv;

?

struct_message data;

struct_message_recv data_answer;

?

#define ESPNOW_ID 8888 // Random 4 digit number

uint8_t receiver_address[] = {0x10, 0x91, 0xA8, 0x32, 0x7B, 0x70}; // Mac address of the receiver. 10:91:A8:32:7B:70

?

uint8_t temp_address[6];

uint8_t last_recv_address[6];

?

String mac;

?

bool need_answer = false;

?

void on_data_recv(const uint8_t * mac, const uint8_t *incomingData, int len) {

? memcpy(&data, incomingData, sizeof(data));

? memcpy(temp_address, mac, 6);

? need_answer = true;

}

?

esp_now_peer_info_t peerInfo;

?

void send_answer(){

? memcpy(peerInfo.peer_addr, temp_address, 6);

? peerInfo.channel = 0;?

? peerInfo.encrypt = false;

?????

? if(esp_now_add_peer(&peerInfo) != ESP_OK){

??? printf("Failed to add peer\r\n");

??? return;

? }

?

? data_answer.answer = true;

?

? esp_now_send(temp_address, (uint8_t *) &data_answer, sizeof(data_answer));

? if(esp_now_del_peer(temp_address) != ESP_OK){

??? printf("Failed to delete peer\r\n");

??? return;

? }

? memcpy(last_recv_address, temp_address, 6);

? memset(temp_address, 0, 6);

?

? set_fastled(CRGB::Green);

}

?

String mac_to_string(uint8_t *addr){

? String mac_str = String(addr[0], HEX) + ":" + String(addr[1], HEX) + ":" + String(addr[2], HEX) + ":"

??? + String(addr[3], HEX) + ":" + String(addr[4], HEX) + ":" + String(addr[5], HEX);

? mac_str.toUpperCase();

? return mac_str;

}

?

void setup(){

? pinMode(BUTTON_PIN, INPUT);

? pinMode(ADC_ENABLE_PIN, OUTPUT);

? pinMode(ADC_PIN, INPUT);

? analogReadResolution(12);

? digitalWrite(ADC_ENABLE_PIN, HIGH);

?

? WiFi.mode(WIFI_STA);

?

? FastLED.addLeds<APA102, APA102_SDI_PIN, APA102_CLK_PIN, BGR>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

? FastLED.setBrightness(160);

? delay(50);

?

? if(esp_now_init() != ESP_OK) {

??? printf("Error initializing ESP-NOW\r\n");

??? return;

? }

?

? set_fastled(CRGB::Blue);

?

? esp_now_register_recv_cb(on_data_recv);

?

? mac = WiFi.macAddress();

? // printf("MAC %s\r\n", mac.c_str());

?

? delay(500);

}

?

unsigned long led_timer = millis();

int hue1 = 0, hue2 = 0;

int brightness = 255;

?

void loop() {

? if(digitalRead(BUTTON_PIN) == 1){

??? set_fastled(CRGB::Red);

??? delay(1000);

??? esp_deep_sleep_start();

? }

?

? if(need_answer){

??? need_answer = false;

??? send_answer();

??? led_timer += 1000;

? }

?

? if(millis() >= led_timer + 15){

??? led_timer = millis();

??? set_fastled(CHSV(hue1, 255, brightness), CHSV(hue2, 255, brightness));

??? hue1 = (hue1 + 1)%255;

??? hue2 = (hue1 + 127)%255;

? }

}

ESP-NOW 到 MQTT 橋

以下代碼是單個設備上 ESP-NOW 到 MQTT 的橋接。要使一切正常,您需要將路由器的頻道更改為固定頻道 1。有關(guān)該頻道或 Home Assistant 集成的更多信息,您應該查看視頻。

要運行此代碼,您需要在頂部部分添加您的 WiFi 憑據(jù),并在重新連接函數(shù)中添加您的 MQTT 憑據(jù)。

該代碼將所有 ESP-NOW 消息轉(zhuǎn)發(fā)為 MQTT 消息,以集成到 Home Assistant 中。主題由標識符“節(jié)點”和四位數(shù)字“ESPNOW_ID”生成。典型的主題可能如下所示:home/node1234/value

#include <Arduino.h>

#include <WiFi.h>

#include <esp_now.h>

#include <esp_wifi.h>

#include <PubSubClient.h>

#include <time.h>

?

const char* ssid = "YOUR_SSID";

const char* password = "YOUR_PWD";

const char* mqtt_server = "YOUR_MQTT_IP"; // Example: 192.168.1.4

?

WiFiClient espClient;

PubSubClient client(espClient);

?

String current_time_str = "";

?

const char* ntpServer = "pool.ntp.org";

const long? gmtOffset_sec = 3600;

const int?? daylightOffset_sec = 3600;

struct tm timeinfo;

int current_seconds = 0;

?

int32_t channel;

?

#define LED_PIN???? 15 // Wemos S2: 15, ThingPlusS2: 13

?

typedef struct struct_message {

??? int id;

??? int value;

??? int battery_level;

??? int single_tap_duration;

} struct_message;

?

typedef struct struct_message_recv {

??? bool answer;

} struct_message_recv;

?

uint8_t temp_address[6];

?

bool need_answer = false;

?

struct_message data;

struct_message_recv data_answer;

bool new_data_received = false;

bool new_data_to_mqtt = false;

unsigned long t_new_data_received = 0;

?

#define N_SINGLETAP_SLOTS?? 10

bool reset_after_single_tap = false;

unsigned long t_reset_single_tap[N_SINGLETAP_SLOTS];

int reset_after_single_tap_id[N_SINGLETAP_SLOTS];

int single_tap_duration[N_SINGLETAP_SLOTS];

?

?

int battery_percentage[] = {4200, 4150, 4110, 4080, 4020, 3980, 3950, 3910, 3870, 3850, 3840, 3820, 3800, 3790, 3770, 3750, 3730, 3710, 3690, 3610, 3270};

int get_battery_percentage(float mv){

? int battery_mv = int(mv);

? int perc = 0;

? for(int i=0; i<=20; i++) if(battery_mv > battery_percentage[20-i]) perc+=5;

? return constrain(perc, 0, 100);

}

?

String get_formatted_time(){

? String t = "";

? if(timeinfo.tm_hour < 10) t += "0";

? t += timeinfo.tm_hour;

? t += ":";

? if(timeinfo.tm_min < 10) t += "0";

? t += timeinfo.tm_min;

? t += ":";

? if(timeinfo.tm_sec < 10) t += "0";

? t += timeinfo.tm_sec;

? return t;

}

?

?

void on_data_recv(const uint8_t * mac, const uint8_t *incomingData, int len) {

? digitalWrite(LED_PIN, 1);

? memcpy(&data, incomingData, sizeof(data));

? memcpy(temp_address, mac, 6);

? need_answer = true;

?

? printf("\r\n");

? printf("Receivid packet from %X:%X:%X:%X:%X:%X\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

? printf("Data - ID: %i, Value: %i, Battery: %i, TapDuration: %i\r\n", data.id, data.value, data.battery_level, data.single_tap_duration);

? printf("\r\n");

?

? if(data.single_tap_duration > 0){

??? reset_after_single_tap = true;

??? bool slot_found = false;

??? for(int i=0; i<N_SINGLETAP_SLOTS; i++){

????? if(single_tap_duration[i] == 0 && !slot_found){

??????? single_tap_duration[i] = data.single_tap_duration;

??????? reset_after_single_tap_id[i] = data.id;

??????? t_reset_single_tap[i] = millis();

??????? slot_found = true;

????? }

??? }

? }

?

? new_data_received = true;

? new_data_to_mqtt = true;

? t_new_data_received = millis();

}

?

esp_now_peer_info_t peerInfo;

?

void send_answer(){

? memcpy(peerInfo.peer_addr, temp_address, 6);

? peerInfo.channel = 0;?

? peerInfo.encrypt = false;

?????

? if(esp_now_add_peer(&peerInfo) != ESP_OK){

??? printf("Failed to add peer\r\n");

??? return;

? }

?

? data_answer.answer = true;

? esp_now_send(temp_address, (uint8_t *) &data_answer, sizeof(data_answer));

? delay(10);

? if(esp_now_del_peer(temp_address) != ESP_OK){

??? printf("Failed to delete peer\r\n");

??? return;

? }

? memset(temp_address, 0, 6);

}

?

?

void callback(char* topic, byte* message, unsigned int length) {

? // digitalWrite(LED_PIN, 1);

? String messageTemp;

?

? for (int i = 0; i < length; i++) {

??? messageTemp += (char)message[i];

? }

? // digitalWrite(LED_PIN, 0);

}

?

void reconnect() {

? while (!client.connected()) {

??? digitalWrite(LED_PIN, 1);

??? if (client.connect("MQTTClient_new", "YOUR_MQTT_USER", "YOUR_MQTT_PWD")) {

????? client.subscribe("home/#");

????? digitalWrite(LED_PIN, 0);

??? } else {

????? printf("Cannot connect to MQTT Server - Restarting in 5s!\r\n");

????? delay(5000);

??? }

? }

}

?

int32_t getWiFiChannel(const char *ssid) {

? if (int32_t n = WiFi.scanNetworks()) {

????? for (uint8_t i=0; i<n; i++) {

????????? if (!strcmp(ssid, WiFi.SSID(i).c_str())) {

????????????? return WiFi.channel(i);

????????? }

????? }

? }

? return 0;

}

?

void setup() {

? pinMode(LED_PIN, OUTPUT);

?

? WiFi.mode(WIFI_AP_STA);

?

? channel = getWiFiChannel(ssid);

? esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);

? printf("WiFi channel: %i\r\n", channel);

?

? printf("Connecting to: %s\r\n", ssid);

? WiFi.begin(ssid, password);

?

? while (WiFi.status() != WL_CONNECTED) {

??? digitalWrite(LED_PIN, 1);

??? delay(150);

??? printf(".\r\n");

??? digitalWrite(LED_PIN, 0);

??? delay(150);

? }

?

? printf("WiFi connected with IP: %s\r\n", WiFi.localIP().toString().c_str());

?

? configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

?

? client.setServer(mqtt_server, 1883);

? // client.setCallback(callback);

?

? if (esp_now_init() != ESP_OK) {

??? printf("Error initializing ESP-NOW\r\n");

??? return;

? }

?

? esp_now_register_recv_cb(on_data_recv);

?

? reconnect();

?

? String payload_mac = String(WiFi.macAddress());

? client.publish("home/s2macaddr", payload_mac.c_str());

}

?

unsigned long t_send_time_running = 0;

?

void loop() {

? if(need_answer){

??? need_answer = false;

??? send_answer();

? }

?

? if(new_data_received){

??? if(new_data_to_mqtt){

????? new_data_to_mqtt = false;

?

????? String topic_value = "home/node" + String(data.id) + "/value";

????? String topic_battery = "home/node" + String(data.id) + "/battery";

????? String topic_batterylevel = "home/node" + String(data.id) + "/batterylevel";

?

????? client.publish(topic_value.c_str(), String(data.value).c_str());

????? client.publish(topic_battery.c_str(), String(data.battery_level).c_str());

????? client.publish(topic_batterylevel.c_str(), String(get_battery_percentage(data.battery_level)).c_str());

??? }

?

??? if(millis() >= t_new_data_received + 1000){

????? digitalWrite(LED_PIN, 0);

????? new_data_received = false;

??? }

? }

?

? if(reset_after_single_tap){

??? bool any_reset_open = false;

??? for(int i=0; i<N_SINGLETAP_SLOTS; i++){

????? if(single_tap_duration[i] > 0){

??????? any_reset_open = true;

??????? if(millis() >= t_reset_single_tap[i] + single_tap_duration[i]){

????????? printf("Send zero\r\n");

????????? String topic_value = "home/node" + String(reset_after_single_tap_id[i]) + "/value";

????????? client.publish(topic_value.c_str(), "0");

?

????????? single_tap_duration[i] = 0;

????????? reset_after_single_tap_id[i] = 0;

??????? }

????? }

??? }

?? ?if(!any_reset_open){

????? reset_after_single_tap = false;

??? }

? }

?

? unsigned int start = millis();

? if(!getLocalTime(&timeinfo)){

??? printf("Failed to obtain time\r\n");

? }

? unsigned int stop = millis();

?

? if(current_seconds != timeinfo.tm_sec){

??? current_seconds = timeinfo.tm_sec;

??? printf("Time: %s\r\n", get_formatted_time());

??? if(timeinfo.tm_sec == 0){

????? client.publish("home/current_time", get_formatted_time().c_str());

??? }

? }

?

? if (!client.connected()) {

??? reconnect();

? }

?

? client.loop();

}

運動傳感器

運動傳感器擴展板基于STMicroelectronics 的LIS3DHTR 。傳感器使用 I2C 與 Picoclick 通信(SDA = GPIO2,SCL = GPIO8)。它有一個超低功率穩(wěn)壓器,可用于通過觸發(fā)中斷來激活 Picoclick。中斷可以通過軟件配置。

硬件

概述

技術(shù)制圖

測量單位為毫米,網(wǎng)格為 0.5 毫米

·??????? 印刷電路板:18 毫米 x 10 毫米

·??????? 厚度:1mm

·??????? 安裝孔:3.2mm

·??????? 圓角半徑:2mm

原理圖

軟件

?

#include <Arduino.h>

#include <WiFi.h>

#include <FastLED.h>

#include <SparkFunLIS3DH.h>

#include <Wire.h>

#include "config.h"

?

LIS3DH lis(I2C_MODE, 0x19); //Default constructor is I2C, addr 0x19.

?

void configIntterupts();

?

void setup(){

? pinMode(BUTTON_PIN, INPUT);

? pinMode(ADC_ENABLE_PIN, OUTPUT);

? pinMode(ADC_PIN, INPUT);

? analogReadResolution(12);

? digitalWrite(ADC_ENABLE_PIN, HIGH);

?

? btStop();

? WiFi.mode(WIFI_OFF);

? setCpuFrequencyMhz(10);

?

? FastLED.addLeds<APA102, APA102_SDI_PIN, APA102_CLK_PIN, BGR>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

? FastLED.setBrightness(160);

? delay(50);

?

? set_fastled(CRGB::Blue);

?

? Wire.begin(SDA_PIN, SCL_PIN);

? delay(100);

?

? lis.settings.accelSampleRate = 50;? //Hz.? Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz

? lis.settings.accelRange = 2;????? //Max G force readable.? Can be: 2, 4, 8, 16

?

? lis.settings.adcEnabled = 0;

? lis.settings.tempEnabled = 0;

? lis.settings.xAccelEnabled = 1;

? lis.settings.yAccelEnabled = 1;

? lis.settings.zAccelEnabled = 1;

?

? lis.begin();

?

? // int dataToWrite = B01001111;

? // lis.writeRegister(LIS3DH_CTRL_REG1, dataToWrite);

?

? // configIntterupts();

}

?

unsigned long t_sensor = millis();

?

void loop() {

? if(digitalRead(BUTTON_PIN) == 1){

??? set_fastled(CRGB::Red);

??? delay(500);

??? esp_deep_sleep_start();

? }

?

? if(millis() >= t_sensor + 500){

??? t_sensor = millis();

??? float x = lis.readFloatAccelX();

??? float y = lis.readFloatAccelY();

??? float z = lis.readFloatAccelZ();

??? printf("X: %f, Y: %f, Z: %f\r\n", x, y, z);

? }

}

?

void configIntterupts(){

? uint8_t dataToWrite = 0;

?

? // //LIS3DH_INT1_CFG??

? // //dataToWrite |= 0x80;//AOI, 0 = OR 1 = AND

? // //dataToWrite |= 0x40;//6D, 0 = interrupt source, 1 = 6 direction source

? // //Set these to enable individual axes of generation source (or direction)

? // // -- high and low are used generically

? // //dataToWrite |= 0x20;//Z high

? // //dataToWrite |= 0x10;//Z low

??// dataToWrite |= 0x08;//Y high

? // //dataToWrite |= 0x04;//Y low

? // //dataToWrite |= 0x02;//X high

? // //dataToWrite |= 0x01;//X low

? // lis.writeRegister(LIS3DH_INT1_CFG, dataToWrite);

?

? // //LIS3DH_INT1_THS??

? // dataToWrite = 0;

? // //Provide 7 bit value, 0x7F always equals max range by accelRange setting

? // dataToWrite |= 0x10; // 1/8 range

? // lis.writeRegister(LIS3DH_INT1_THS, dataToWrite);

?

? // //LIS3DH_INT1_DURATION?

? // dataToWrite = 0;

? // //minimum duration of the interrupt

? // //LSB equals 1/(sample rate)

? // dataToWrite |= 0x01; // 1 * 1/50 s = 20ms

? // lis.writeRegister(LIS3DH_INT1_DURATION, dataToWrite);

?

? //LIS3DH_CLICK_CFG??

? dataToWrite = 0;

? //Set these to enable individual axes of generation source (or direction)

? // -- set = 1 to enable

? //dataToWrite |= 0x20;//Z double-click

? dataToWrite |= 0x10;//Z click

? //dataToWrite |= 0x08;//Y double-click

? dataToWrite |= 0x04;//Y click

? //dataToWrite |= 0x02;//X double-click

? dataToWrite |= 0x01;//X click

? lis.writeRegister(LIS3DH_CLICK_CFG, dataToWrite);

?

? //LIS3DH_CLICK_SRC

? dataToWrite = 0;

? //Set these to enable click behaviors (also read to check status)

? // -- set = 1 to enable

? //dataToWrite |= 0x20;//Enable double clicks

??dataToWrite |= 0x04;//Enable single clicks

? //dataToWrite |= 0x08;//sine (0 is positive, 1 is negative)

? dataToWrite |= 0x04;//Z click detect enabled

? dataToWrite |= 0x02;//Y click detect enabled

? dataToWrite |= 0x01;//X click detect enabled

? lis.writeRegister(LIS3DH_CLICK_SRC, dataToWrite);

?

? //LIS3DH_CLICK_THS??

? dataToWrite = 0;

? //This sets the threshold where the click detection process is activated.

? //Provide 7 bit value, 0x7F always equals max range by accelRange setting

? dataToWrite |= 0x0A; // ~1/16 range

? lis.writeRegister(LIS3DH_CLICK_THS, dataToWrite);

?

? //LIS3DH_TIME_LIMIT?

? dataToWrite = 0;

? //Time acceleration has to fall below threshold for a valid click.

? //LSB equals 1/(sample rate)

? dataToWrite |= 0x08; // 0x08: 8 * 1/50 s = 160ms

? lis.writeRegister(LIS3DH_TIME_LIMIT, dataToWrite);

?

? //LIS3DH_TIME_LATENCY

? dataToWrite = 0;

? //hold-off time before allowing detection after click event

? //LSB equals 1/(sample rate)

? dataToWrite |= 0x0F; // 4 * 1/50 s = 160ms,

? lis.writeRegister(LIS3DH_TIME_LATENCY, dataToWrite);

?

? //LIS3DH_TIME_WINDOW

? dataToWrite = 0;

? //hold-off time before allowing detection after click event

? //LSB equals 1/(sample rate)

? dataToWrite |= 0x8F; // 16 * 1/50 s = 320ms

? lis.writeRegister(LIS3DH_TIME_WINDOW, dataToWrite);

?

? //LIS3DH_CTRL_REG5

? //Int1 latch interrupt and 4D on? int1 (preserve fifo en)

? lis.readRegister(&dataToWrite, LIS3DH_CTRL_REG5);

? dataToWrite &= 0xF3; //Clear bits of interest

? dataToWrite |= 0x08; //Latch interrupt (Cleared by reading int1_src)

? //dataToWrite |= 0x04; //Pipe 4D detection from 6D recognition to int1?

? lis.writeRegister(LIS3DH_CTRL_REG5, dataToWrite);

?

? //LIS3DH_CTRL_REG3

? //Choose source for pin 1

? dataToWrite = 0;

? dataToWrite |= 0x80; //Click detect on pin 1

? // dataToWrite |= 0x40; //AOI1 event (Generator 1 interrupt on pin 1)

? // dataToWrite |= 0x20; //AOI2 event ()

? //dataToWrite |= 0x10; //Data ready

? //dataToWrite |= 0x04; //FIFO watermark

? //dataToWrite |= 0x02; //FIFO overrun

? lis.writeRegister(LIS3DH_CTRL_REG3, dataToWrite);

?

? // //LIS3DH_CTRL_REG6

? // //Choose source for pin 2 and both pin output inversion state

? // dataToWrite = 0;

? // // dataToWrite |= 0x80; //Click int on pin 2

? // // dataToWrite |= 0x40; //Generator 1 interrupt on pin 2

? // //dataToWrite |= 0x10; //boot status on pin 2

? // //dataToWrite |= 0x02; //invert both outputs

? // lis.writeRegister(LIS3DH_CTRL_REG6, dataToWrite);

}


基于ESP32開發(fā)智能物聯(lián)網(wǎng)微型設備的評論 (共 條)

分享到微博請遵守國家法律
舟山市| 武乡县| 漾濞| 昌乐县| 茂名市| 云南省| 安平县| 宁阳县| 牟定县| 区。| 明星| 彭泽县| 武隆县| 子长县| 丹阳市| 方城县| 图们市| 枝江市| 六安市| 石首市| 昂仁县| 长葛市| 新民市| 那曲县| 澎湖县| 义马市| 宜丰县| 青浦区| 得荣县| 江山市| 陈巴尔虎旗| 和龙市| 大余县| 临汾市| 东辽县| 宝山区| 普洱| 皋兰县| 改则县| 德惠市| 内丘县|