прошу прощения, написал фигню.
Что за идиотская привычка использовать <= в for
- запутывает!!
#include <ArduinoJson.h>
#include <ArduinoJson.hpp>
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#else
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include "index.h"
const char *ssid = **********";
const char *password = "**************";
#ifdef ARDUINO_ARCH_ESP8266
const int LED_PIN = LED_BUILTIN;
#define LED_ON LOW
#define LED_OFF HIGH
byte const SENSOR_PIN = A0;
#else
const int LED_PIN = 2;
#define LED_ON HIGH
#define LED_OFF LOW
byte const SENSOR_PIN = 34;
#endif
#include "DHT.h" //https://github.com/adafruit/Adafruit_Sensor
#define DHTPIN D1
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
bool ledState = false;
//byte const pinLED = LED_BUILTIN;
int sensor = 0;
float humidity = 0;
float tempC = 0;
float tempF = 0;
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
#define LATCHPIN D2 //GREEN 9 chip CD4021
#define DATAPIN D3 //YELLOW 3 chip CD4021
#define CLOCKPIN D4 // GREY 10 chip CD4021
byte switchVar1 = 72; //01001000 регистр сдвига CD4021
byte switchVar2 = 159; //10011111
void setup() {
Serial.begin(74880);
while (!Serial) { ; }
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LED_OFF);
pinMode(LATCHPIN, OUTPUT);
pinMode(CLOCKPIN, OUTPUT);
pinMode(DATAPIN, INPUT);
pinMode(D2, OUTPUT);
digitalWrite(D2, LOW);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print('.');
}
timeoutNet();
// attach AsyncWebSocket
ws.onEvent(onWsEvent);
server.addHandler(&ws);
// respond to GET requests on URL /heap
server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *r) {
r->send_P(200, "text/html", htmlPage);
});
server.on("/health", HTTP_GET, [](AsyncWebServerRequest *r) {
r->send(200, "text/plain", "ok");
});
server.begin();
}
void loop() {
ws.cleanupClients();
JsonDocument doc;
static unsigned long last = 0;
if (millis() - last > 3000) {
last = millis();
// cheek register СВ4021, contact with rezistors 1,5kOm
digitalWrite(LATCHPIN, 1);
delayMicroseconds(20);
digitalWrite(LATCHPIN, 0);
//--- 1 register СВ4021
switchVar1 = shiftIn(DATAPIN, CLOCKPIN);
for (int n = 0; n <= 7; n++) {
if (switchVar1 & (1 << n)) { // array[0-7]
ws.textAll(String("P=") + "1"); //nclose
} else {
ws.textAll(String("P=") + "0"); //nopen
}
}
//--- 2 register СВ4021
switchVar2 = shiftIn(DATAPIN, CLOCKPIN);
for (int n = 0; n <= 7; n++) {
if (switchVar2 & (1 << n)) { // array[7-15]
ws.textAll(String("P=") + "1"); //nclose
} else {
ws.textAll(String("P=") + "0"); //nopen
}
}
updateSensors();
ws.textAll(String("TEMP:") + tempC);
ws.textAll(String("HUMID:") + byte(humidity));
ws.textAll(String("SENSOR:") + byte(sensor));
// Write JSON document
//serializeJsonPretty(doc, client);
}
}
void updateSensors() {
sensor = map(analogRead(SENSOR_PIN), 0, 1023, 0, 100);
humidity = dht.readHumidity();
tempC = dht.readTemperature(); // Read temperature as Celsius
tempF = dht.readTemperature(true); // Read temperature as Fahrenheit (isFahrenheit = true)
//if any value is isnan (not a number) then there is an error
if (isnan(humidity) || isnan(tempC) || isnan(tempF)) {
Serial.println("Error reading from the DHT11.");
} else {
String data = "";
data = String(data + sensor);
data = String(data + "|");
data = String(data + byte(humidity));
data = String(data + "|");
data = String(data + tempC);
data = String(data + "|");
data = String(data + tempF);
Serial.println(data); // display the data in the serial monitor
}
}
void onWsEvent(AsyncWebSocket *srv, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
if (type == WS_EVT_CONNECT) {
client->text(ledState ? "ON" : "OFF");
return;
}
if (type == WS_EVT_DATA) {
AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
String msg;
msg.reserve(len);
for (size_t i = 0; i < len; i++) msg += (char)data[i];
if (msg == "TOGGLE") {
ledState = !ledState;
digitalWrite(LED_PIN, ledState ? LED_ON : LED_OFF);
ws.textAll(ledState ? "ON" : "OFF");
}
}
}
}
void timeoutNet() { // connection with timeout
int count = 0;
digitalWrite(LED_BUILTIN, HIGH);
while ((WiFi.status() != WL_CONNECTED) && count < 17) {
Serial.print(".");
count++;
delay(500);
}
digitalWrite(LED_BUILTIN, LOW);
if (WiFi.status() != WL_CONNECTED) {
Serial.println("");
Serial.print("Failed to connect to ");
while (1)
;
}
Serial.println(ssid);
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
// 2 регистра сдвига
byte shiftIn(int DATA, int CLK) {
int i;
int temp = 0;
byte pinState;
byte inDATE = 0;
pinMode(CLK, OUTPUT);
pinMode(DATA, INPUT);
for (i = D2; i >= 0; i--) {
digitalWrite(CLK, 0);
delayMicroseconds(2);
temp = digitalRead(DATA);
if (temp) {
pinState = 1;
// несмотря ни на что, задаем биту значение «0»:
inDATE = inDATE | (1 << i);
} else {
pinState = 0;
}
digitalWrite(CLK, 1);
}
return inDATE;
}
Страница то вообще грузится?
смотри строку 194, // это в html не комментирует строку, в html так должно быть <!– –>
208 строка тож неправильно.
в js явно не хватает скобок, но это так на первый взгляд.
Тут не WS не работает, тут ваще страница криво собрана, да еще и скрипт перед body он откуда будет брать const $s = document.getElementById(‘status’); и прочее когда их еще нет?
в css не силен , надеюсь все нормально.
Пойду чая попью, потом еще гляну.
есть косяки дома все было ок, сейчас на работе поэтому перенёс по памяти и что то криво срослось , сам пробую исправить
нашел что функция byte shiftIn(DA,CLK) надо переименовать т.к. есть такая же, но с др. параметрами. например SHIFT(D,C)
// 2 регистра сдвига
byte SHIFT(int DATA, int CLK) {
int i;
int temp = 0;
byte pinState;
byte inDATE = 0;
pinMode(CLK, OUTPUT);
pinMode(DATA, INPUT);
for (i = D2; i >= 0; i--) {
digitalWrite(CLK, 0);
delayMicroseconds(2);
temp = digitalRead(DATA);
if (temp) {
pinState = 1;
// несмотря ни на что, задаем биту значение «0»:
inDATE = inDATE | (1 << i);
} else {
pinState = 0;
}
digitalWrite(CLK, 1);
}
return inDATE;
}
// cheek register СВ4021, contact with rezistors 1,5kOm
digitalWrite(LATCHPIN, 1);
delayMicroseconds(20);
digitalWrite(LATCHPIN, 0);
//--- 1 register СВ4021
switchVar1 = SHIFT(DATAPIN, CLOCKPIN);
for (int n = 0; n <= 7; n++) {
if (switchVar1 & (1 << n)) { // array[0-7]
client.print("1");
client.print("|"); //nclose
} else {
client.print("0");
client.print("|"); //nopen
}
}
//--- 2 register СВ4021
switchVar2 = SHIFT(DATAPIN, CLOCKPIN);
for (int n = 0; n <= 7; n++) {
if (switchVar2 & (1 << n)) { // array[7-15]
client.print("1");
client.print("|"); //nclose
} else {
client.print("0");
client.print("|"); //nopen
}
}
В общем проблема с HTML и JS.
В коде тоже бардак, но причесывать не буду. Тут уж сам.
Смотри я отключил все что касается регистров и DHT11 у меня этого нет.
Температура и влажность передаются рандомные, все работает, а данные с регистров надо передавать одним пакетом, иначе будет постоянно терять соединение. css тоже немного исправил, с цветами была беда.
например такой пакет
{“t”:32,“h”:54,“r11”:0,“r12”:0,“r13”:0,“r14”:0,“r15”:0,“r16”:0,“r17”:0,“r18”:0,“r21”:0,“r22”:0,“r23”:0,“r24”:0,“r25”:0,“r26”:0,“r27”:0,“r28”:0}
если здесь ArduinoJson Assistant 7 вставить JSON то конструктор нарисует код. все просто.
на стороне клиента получаем JSON и распихиваем по ячейкам значения, там вообще все циклами можно сделать если количество передаваемых параметров статично.
ino
#include <ArduinoJson.h>
#include <ArduinoJson.hpp>
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#else
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include "index.h"
const char *ssid = "***";
const char *password = "***";
#ifdef ARDUINO_ARCH_ESP8266
const int LED_PIN = LED_BUILTIN;
#define LED_ON LOW
#define LED_OFF HIGH
byte const SENSOR_PIN = A0;
#else
const int LED_PIN = 2;
#define LED_ON HIGH
#define LED_OFF LOW
byte const SENSOR_PIN = 34;
#endif
//#include "DHT.h" //https://github.com/adafruit/Adafruit_Sensor
#define DHTPIN D1
#define DHTTYPE DHT11
//DHT dht(DHTPIN, DHTTYPE);
bool ledState = false;
//byte const pinLED = LED_BUILTIN;
int sensor = 0;
float humidity = 0;
float tempC = 0;
float tempF = 0;
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
//#define LATCHPIN D2 //GREEN 9 chip CD4021
//#define DATAPIN D3 //YELLOW 3 chip CD4021
//#define CLOCKPIN D4 // GREY 10 chip CD4021
byte switchVar1 = 72; //01001000 регистр сдвига CD4021
byte switchVar2 = 159; //10011111
void setup() {
Serial.begin(115200);
while (!Serial) { ; }
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LED_OFF);
//pinMode(LATCHPIN, OUTPUT);
//pinMode(CLOCKPIN, OUTPUT);
//pinMode(DATAPIN, INPUT);
//pinMode(D2, OUTPUT);
//digitalWrite(D2, LOW);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print('.');
}
timeoutNet();
// attach AsyncWebSocket
ws.onEvent(onWsEvent);
server.addHandler(&ws);
// respond to GET requests on URL /heap
server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *r) {
r->send_P(200, "text/html", htmlPage);
});
server.on("/health", HTTP_GET, [](AsyncWebServerRequest *r) {
r->send(200, "text/plain", "ok");
});
server.begin();
}
void loop() {
ws.cleanupClients();
JsonDocument doc;
static unsigned long last = 0;
if (millis() - last > 3000) {
last = millis();
// cheek register СВ4021, contact with rezistors 1,5kOm
//digitalWrite(LATCHPIN, 1);
//delayMicroseconds(20);
//digitalWrite(LATCHPIN, 0);
//--- 1 register СВ4021
//switchVar1 = shiftIn(DATAPIN, CLOCKPIN);
//здесть ненадо дергать сокет, надо собрать 1 пакет данных и отправить
// на стороне клиена расшифровать и расставить по ячейкам.
/*
switchVar1 = 125;
for (int n = 0; n <= 7; n++) {
if (switchVar1 & (1 << n)) { // array[0-7]
ws.textAll(String("P=") + "1"); //nclose
} else {
ws.textAll(String("P=") + "0"); //nopen
}
}
//--- 2 register СВ4021
//switchVar2 = shiftIn(DATAPIN, CLOCKPIN);
switchVar2 = 252;
for (int n = 0; n <= 7; n++) {
if (switchVar2 & (1 << n)) { // array[7-15]
ws.textAll(String("P=") + "1"); //nclose
} else {
ws.textAll(String("P=") + "0"); //nopen
}
}
*/
updateSensors();
ws.textAll(String("TEMP:") + tempC);
ws.textAll(String("HUMID:") + byte(humidity));
ws.textAll(String("SENSOR:") + byte(sensor));
// Write JSON document
//serializeJsonPretty(doc, client);
}
}
void updateSensors() {
sensor = map(analogRead(SENSOR_PIN), 0, 1023, 0, 100);
humidity = random(0,100);
tempC = random(-273,100); // Read temperature as Celsius
tempF = random(459,212); // Read temperature as Fahrenheit (isFahrenheit = true)
/*humidity = dht.readHumidity();
tempC = dht.readTemperature(); // Read temperature as Celsius
tempF = dht.readTemperature(true); // Read temperature as Fahrenheit (isFahrenheit = true)
*/
//if any value is isnan (not a number) then there is an error
if (isnan(humidity) || isnan(tempC) || isnan(tempF)) {
Serial.println("Error reading from the DHT11.");
} else {
String data = "";
data = String(data + sensor);
data = String(data + "|");
data = String(data + byte(humidity));
data = String(data + "|");
data = String(data + tempC);
data = String(data + "|");
data = String(data + tempF);
Serial.println(data); // display the data in the serial monitor
}
}
void onWsEvent(AsyncWebSocket *srv, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
if (type == WS_EVT_CONNECT) {
client->text(ledState ? "ON" : "OFF");
return;
}
if (type == WS_EVT_DATA) {
AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
String msg;
msg.reserve(len);
for (size_t i = 0; i < len; i++) msg += (char)data[i];
if (msg == "TOGGLE") {
ledState = !ledState;
digitalWrite(LED_PIN, ledState ? LED_ON : LED_OFF);
ws.textAll(ledState ? "ON" : "OFF");
}
}
}
}
void timeoutNet() { // connection with timeout
int count = 0;
//digitalWrite(LED_BUILTIN, HIGH);
while ((WiFi.status() != WL_CONNECTED) && count < 17) {
Serial.print(".");
count++;
delay(500);
}
//digitalWrite(LED_BUILTIN, LOW);
if (WiFi.status() != WL_CONNECTED) {
Serial.println("");
Serial.print("Failed to connect to ");
while (1)
;
}
Serial.println(ssid);
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
// 2 регистра сдвига
byte shiftIn(int DATA, int CLK) {
int i;
int temp = 0;
byte pinState;
byte inDATE = 240;
/*
pinMode(CLK, OUTPUT);
pinMode(DATA, INPUT);
for (i = D2; i >= 0; i--) {
digitalWrite(CLK, 0);
delayMicroseconds(2);
temp = digitalRead(DATA);
if (temp) {
pinState = 1;
// несмотря ни на что, задаем биту значение «0»:
inDATE = inDATE | (1 << i);
} else {
pinState = 0;
}
digitalWrite(CLK, 1);
}
*/
return inDATE;
}
index.h
const char htmlPage[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ESP WebSocket</title>
<style>
body {
font-family: system-ui, -apple-system, Arial, sans-serif;
max-width: 640px;
margin: 48px auto;
padding: 0 16px;
background: black;
}
h1 {
color: aqua;
font-family: sans-serif;
font-weight: normal;
margin: 3px;
}
th {
color: orangered;
font-family: sans-serif;
font-size: 15px;
padding-left: 8px;
padding-right: 8px;
border: 1px solid white;
border-radius: 10px;
}
td {
color: black;
font-family: cursive;
text-align: center;
font-size: 20px;
padding: 1px 3px;
border: 1px solid #3e3e3e;
border-radius: 5px;
}
.form {
border: 3px solid grey;
margin-bottom: 20px;
box-shadow: 5px 8px 20px 0px grey;
}
.card {
background: #fff;
padding: 24px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, .06);
}
.status {
font-size: 18px;
padding: 12px;
border-radius: 8px;
margin: 12px 0;
text-align: center;
}
.on {
background: #2e7d32;
color: #fff;
}
.off {
background: #c62828;
color: #fff;
}
button {
width: 100%;
padding: 14px 16px;
font-size: 16px;
border: 0;
border-radius: 10px;
cursor: pointer;
background: #1976d2;
color: #fff;
}
.mono {
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
</style>
</head>
<body>
<div class="card">
<h1>ESP WebSocket</h1>
<div id="status" class="status off">Соединение...</div>
<button id="btn">Переключить светодиод</button>
<div class="form">
<h1>СЕНСОРЫ</h1>
<table>
<!-- таблица отображаемых данных -->
<tr>
<td>TEMP</td>
<td>HUMIDITY</td>
<td>SENSOR</td>
<td>SOCKET</td>
</tr>
<tr>
<td><span id="temp" class="mono"></span><span> °C</span></td>
<td><span id="humidity" class="mono"></span><span> %</span></td>
<td><span id="sensor" class="mono"></span><span> %</span></td>
<td><span id="conn" class="mono"></span></td>
</tr>
<!-- register -->
<tr>
<td><span id='pin_0'></span></td>
<td><span id='pin_1'></span></td>
<td><span id='pin_2'></span></td>
<td><span id='pin_3'></span></td>
</tr>
<tr>
<td><span id='pin_4'></span></td>
<td><span id='pin_5'></span></td>
<td><span id='pin_6'></span></td>
<td><span id='pin_7'></span></td>
</tr>
<tr>
<td><span id='pin_8'></span></td>
<td><span id='pin_9'></span></td>
<td><span id='pin_12'></span></td>
<td><span id='pin_13'></span></td>
</tr>
</table>
</div>
</div>
<script>
let ws = null;
let timer = null;
const $s = document.getElementById('status');
const $c = document.getElementById('conn');
const $d = document.getElementById('sensor');
const $b = document.getElementById('btn');
const $t = document.getElementById('temp');
const $h = document.getElementById('humidity');
function setConn(x) {
$c.textContent = x ? 'подключено' : 'отключено';
$c.style.color = x ? 'green' : 'red';
}
function reconnect() {
if (timer) return;
timer = setTimeout(() => {
timer = null;
connect();
}, 2000);
}
function connect() {
try {
ws = new WebSocket('ws://' + window.location.host + '/ws');
} catch (e) {
reconnect();
return;
}
ws.onopen = () => setConn(true);
ws.onmessage = e => {
const m = e.data || '';
console.log(`lDataJSON - ${m}`);
if (m === 'ON') {
$s.className = 'status on';
$s.textContent = 'Светодиод включён';
} else if (m === 'OFF') {
$s.className = 'status off';
$s.textContent = 'Светодиод выключён';
} else if (m.startsWith('SENSOR:')) {
$d.textContent = m.split(':')[1];
} else if (m.startsWith('TEMP:')) {
$t.textContent = m.split(':')[1];
} else if (m.startsWith('HUMID:')) {
$h.textContent = m.split(':')[1];
}
};
ws.onclose = (e) => {
setConn(false);
$s.className = 'status off';
$s.textContent = 'Соединение потеряно';
console.log('Socket is closed. Reconnect will be attempted in 2 seconds.', e.reason);
reconnect();
};
ws.onerror = (err) => {
console.error('Socket encountered error: ', err.message, 'Closing socket');
ws.close();
};
}
$b.addEventListener('click', () => {
if (ws && ws.readyState === WebSocket.OPEN) ws.send('TOGGLE');
else alert('Нет соединения');
});
connect();
</script>
</body>
</html>
)rawliteral";
Если запутаешься пиши, попробуем настроить.
думаю отправить так { “pin”: [ 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1 ] }
void loop() { ws.cleanupClients(); static unsigned long last = 0; if (millis() - last > 2000) { last = millis(); JsonDocument doc; // Create the "digital" array JsonArray pin = doc["pin"].to<JsonArray>(); for (int i = 0; i = 15; i++) { // cheek register СВ4021, contact with rezistors 1,5kOm uint8_t valueOfPin = sr.get(i); //read value of pin [i] on register char b = valueOfPin; pin.add(b); } serializeJson(doc, pin); } }
просто отправить массив не получается
ошибки не пойму
Compilation error: grpc: error while marshaling: string field contains invalid UTF-8
Вот тут решение есть, видимо кириллица где-то в пути в библиотекам
Такой цикл работать не будет
собрал на 1 регистре
void loop() {
ws.cleanupClients();
static unsigned long last = 0;
if (millis() - last > 1000) {
last = millis();
JsonDocument doc;
// Create the "digital" array
// cheek register СВ4021, contact with rezistors 1,5kOm
digitalWrite(LATCHPIN, 1);
delayMicroseconds(20);
digitalWrite(LATCHPIN, 0);
//--- 1 register СВ4021
JsonArray pin = doc["pin"].to<JsonArray>();
switchVar1 = SHIFT(DATAPIN, CLOCKPIN);
Serial.println(switchVar1);
for (int n = 0; n <= 7; n++) {
if (switchVar1 & (1 << n)) { // array[0-7]
pin.add(1);
Serial.print("1");
Serial.print("|"); //nclose
} else {
pin.add(0);
Serial.print("0");
Serial.print("|"); //nopen
}
}
String output;
doc.shrinkToFit(); // optional
serializeJson(doc, Serial);
}
}
20:03:57.124 -> 0|0|0|0|0|0|0|0|{"pin":[0,0,0,0,0,0,0,0]}0
изменения есть при замыкании 1-8 входов
теперь данные надо вывести в браузере. ??? т.е. как то сдесь все описать
const $p = document.getElementById('pin')
ws.onmessage = e => {
const m = e.data || '';
if (m.startsWith('pin')) {
var arrayS == e.data.split(,);
for (var i = 0; i < 8; i++) {
if (m === '1') {
$p.textContent = m.split('|')[1];
} else if (m === '0') {
$p.textContent = m.split('|')[1];
}
