ESP8266 грабли опыт и размышления

Беру тестовый txt на 3,45кб (через браузер нахожу и через кнопку upload отправляю). В браузере пишет "File upload", в мониторе:

2 - это по запросу Serial.println(uploadHTML.status);
test7.txt - это по запросу Serial.println(uploadHTML.filename);
3542 - это по запросу Serial.println(uploadHTML.totalSize);
upload! - это он сразу перепрыгнул на uploadHTML.status == UPLOAD_FILE_END
0 - это по запросу Serial.println (uploadFile); то есть файла нет
close!

Только когда я убираю все условия на статус (то есть без if else и == статусов), тогда он записывает последний кусок файла, а так программа ведет себя, как показал выше...
 
А такой пример не запустится, интересно?
Там, вроде как с картой работает.
 
Надо будет посмотреть и разобрать... Завтра уже отпишусь, что да как...:)
 
А такой пример не запустится, интересно?
Там, вроде как с картой работает.
Просмотрел код и понял свою ошибку. У меня запрос /upload приходит, а ответ обратно нет. Сделал еще одну функцию void returnOK() как в примере и прописал server.on("/upload", HTTP_POST, [](){ returnOK(); }, handleFileUpload); вместо server.on("/upload",HTTP_POST, handleFileUpload); , а так же убрал из void loop() - server.upload(); , чтобы server.upload(); в постоянном цикле не был. В итоге записывает и обрабатывает, но когда архив пытаешься переслать - он с ошибками записывается, хотя проверку побайтовую я тоже прописывал. Я думаю задержки между выполнением запросов поставить побольше (экспериментальным путем буду подбирать), а то не успевает обрабатывать. Короче, сталось только время записи синхронизировать (показывает, что файл записан в 2099 году), разобраться с записью архивов на SD и всё:)

Добавленные проверки в handleFileUpload() в коде ниже:

void handleFileUpload() {
if(server.uri() != "/upload") return; // если путь запроса не равен /upload - return
HTTPUpload& uploadHTML = server.upload();
delay(20);
Serial.println(uploadHTML.status);
Serial.println(uploadHTML.filename);
Serial.println(uploadHTML.totalSize);
static size_t bytesReceived = 0; // счетчик байтов
bool fileCreated = false;
if (uploadHTML.status == UPLOAD_FILE_START || uploadHTML.status == UPLOAD_FILE_WRITE) {
Serial.println(uploadHTML.filename);
if (uploadHTML.status == UPLOAD_FILE_START) {
// Начало загрузки файла - открываем файл для записи
String filename = uploadHTML.filename;
if (SD.exists("/" + filename) ) { // проверяем, существует ли файл с таким именем
server.send(500, "text/plain", "Error: file already exists");
Serial.println("Error: file already exists");
return;
}
uploadFile = SD.open("/" + filename, "a");
if (!uploadFile) { // проверяем, можно ли создать файл
server.send(500, "text/plain", "Error: could not create file");
Serial.println("Error: could not create file");
return;
}
Serial.println("File created");
fileCreated = true;
bytesReceived = 0; // сбрасываем счетчик байтов
}

else if (uploadHTML.status == UPLOAD_FILE_WRITE && uploadHTML.totalSize > 0) {
// Запись части файла
size_t bytesWritten = 0;
if (bytesReceived + uploadHTML.currentSize <= uploadHTML.totalSize) { // сверяем счетчик байтов с общим размером
bytesWritten = uploadFile.write(uploadHTML.buf, uploadHTML.currentSize);
bytesReceived += uploadHTML.currentSize; // увеличиваем счетчик байтов
} else {
server.send(500, "text/plain", "Error: byte counter exceeds total size");
Serial.println("Error: byte counter exceeds total size");
delay(20);
}
Serial.println("Bytes written: " + String(bytesWritten) );
delay(20);
// Если размер буфера не превышен, продолжаем загрузку
if (bytesWritten != uploadHTML.currentSize) {
server.send(500, "text/plain", "Error: write error");
Serial.println("Error: write error");
delay(20);
}
}
// Закрываем файл
} else if (uploadHTML.status == UPLOAD_FILE_END) {
if (fileCreated) {
uploadFile.close();
Serial.println("File closed");
if (bytesReceived != uploadHTML.totalSize) { // сверяем счетчик байтов с общим размером файла
SD.remove("/" + uploadHTML.filename); // если файл не полный, удаляем
server.send(500, "text/plain", "Error: incomplete file");
Serial.println("Error: incomplete file");
return;
}
if (!uploadFile) { // проверяем, был ли файл успешно закрыт
server.send(500, "text/plain", "Error: could not close file");
Serial.println("Error: could not close file");
return;
}
server.send(200, "text/plain", "File uploaded successfully");
Serial.println("File uploaded successfully");
}
}
}


Пока это выглядит вот так : эта станица записана на Wemos, IP - который назначили, на странице пока только две кнопки, для выбора файла и загрузки (но ведь можно еще добавить разных). Эта страница открывается на смартфоне и можно с смартфона передать файлы, да и управлять чем хочешь, если кнопок добавить и обработчиков. Буду доделывать... На скрине видно, что размер файла test7.txt на диске и загруженного совпадает. Логика последовательности запросов не нарушена, а это уже радует. После загрузки чего-то на странице ничего не показывает, а должен. Это же самая 0,001 версия...:D

upload_wemosD1miniSD.jpg
 
  • Последнее редактирование:
Последнее редактирование:
Выкладываю готовый проверенный проект для передачи по WiFi с компьютера (телефона, планшета) файла и записи его на SD карту.
При включении сначала проверяется наличие SD карты, после этого назначается IP адрес Wemos D1 mini v2 и происходит запуск сервера. Пины для подключения SD shield - стандартные D8 D7 D6 D5 3.3V GND. Скорость передачи около 1мин 30 сек - 10Мб файл. Подключение через браузер. Пишете в строке назначенный IP адрес и переходите на страницу Wemos D1 mini v2. С помощью кнопки "обзор" выбираете нужный Вам для передачи файл, с помощью кнопки "upload" идет передача данных. Файлы передает только на английском языке (на русском имя файла кракозябра получается). Дождитесь сообщения "File upload" и Ваш файл уже на флешке. Я делал на VS code, там библиотеки подключаются полуавтоматически, для Arduino IDE прийдется те библиотеки, которых не будет хватать, загружать вручную. Победил проблему с архивами, теперь все разархивируется. Вся информация о работе выводится на монитор порта. Для теста открывал в проводнике телефона файлы фото по одному и передавал. :) файл на с++ ниже в zip архиве. В будущем хочу добавить кнопки на страницу для управления контроллером GRBL через RX TX. Для подключения WiFi введите свои значения ssid и password (только что исправил архив).


Screenshot_20230305-105315.pngScreenshot_20230305-105340.pngIMG_20230305_105101.jpg
 

Вложения

  • SD_wifi.zip
    1.2 KB · Просмотры: 6
А схему соединения можно показать на фотке хотя бы. А еще лучше схему всех составляющих от станка до компьютера. И потом. Разве не проще переписать программу с компьютера прямо на флеш-карту через USB разъем?
 
  • Последнее редактирование:
Последнее редактирование:
А схему соединения можно показать на фотке хотя бы. А еще лучше схему всех составляющих от станка до компьютера. И потом. Разве не проще переписать программу с компьютера прямо на флеш-карту через USB разъем?
Конечно. От станка до компьютера это еще в проекте, а пока просто WiFi флешка :) Схема ниже...

wemosD1.jpg
Ваши сообщения автоматически объединены:

...но Wemos mini очень универсальна в этом плане и модули друг на друга как конструктор собираются, но я проводами привык...

55a0.jpeg
Ваши сообщения автоматически объединены:

Разве не проще переписать программу с компьютера прямо на флеш-карту через USB разъем?
А представьте себя где-нибудь со станком в гараже (с оффлайн контроллером) или еще для чего нужно записать информацию на SD карту... Раздаете WiFi по телефону или в пределах сети (только заранее пропишите параметры в wemos), скачайте с почты файл (или что нужно) и с того же телефона запишите на флешку, причем флешку можно любую впендюрить. А в будущем эконом контроллер, который не требует ничего, кроме WiFi, который передаст выбранный файл с SD на станок, причем управления станка будет через страницу сервера wemos d1 mini. Ни программ, ни кренделя или других программ, ни мелкого дисплея - все на странице... Но я пока первый шаг сделал, который полезен для того, чтобы флешка работала как автономное устройство.(y)
 
Конечно. От станка до компьютера это еще в проекте, а пока просто WiFi флешка :) Схема ниже...

wemosD1.jpg
Ну вот, другое дело. Осталось немного офлайн-контроллер. А по мне бы лучше с телефона или с планшета станком при этом управлять через UART-порт. Приложение установил (как сейчас в Инектра сейчас через Блютуз) и работай себе.
 
  • Последнее редактирование:
Последнее редактирование:




Может кому полезно будет HTLM CSS JS и AJAX на ESP8266 (можно и к ESP32 прикрутить)
 
Форумчане, как только стал люминий потихоньку обрабатывать, вопрос станка в комнате сразу отпал - не место ему! Перенес на лоджию, но это все присказка... В итоге встал вопрос об срочном универсальном пульте через esp8266 (у дядьки OlegK пульт отличный, но заказывать с Али очень долго, а горит уже вчера:)), чтобы поставить например в центр заготовки ноль. Часок помучился с кодом и получилось, что получилось:confused:. Идея проста как 5 копеек :

Отправляем через порт 8888 по WiFi сообщение компьютеру при нажатии кнопки, "ловим" сообщение на сервере через Питон и используя библиотеку keyboard и имитируем нажатие. В кенделе включаем управление с клавиатуры, а как у меня в NC Studio использую горячие клавиши (в новых кенделах тоже горячие клавиши по-моему есть). В итоге универсальный пульт готов. Ща кнопки припаяю и фото выложу. Использовал пока 4 кнопки, но потенциал идеи есть и не маленький. Кнопки без подтяжек, просто пока сделал на пин+земля

Из минусов - никак не могу избавится от микро-микро задержки, все равно малюсенькие, почти не заметные глазу рывки (проверял в кенделе) есть, но это, наверное, плата за простоту конструкции (или мои крывые руки в программировании).

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>

const char* ssid = "*****"; SSID WiFi
const char* password = "*****"; Пароль от WiFi
const char* serverIP = "*****"; IP адрес компьютера
const int serverPort = 8888;

const int buttonPin1 = D1;
const int buttonPin2 = D2;
const int buttonPin3 = D3;
const int buttonPin4 = D4;

WiFiClient client;

volatile bool buttonPressed1 = false;
volatile bool buttonPressed2 = false;
volatile bool buttonPressed3 = false;
volatile bool buttonPressed4 = false;

void ICACHE_RAM_ATTR handleButtonPress1() {
buttonPressed1 = true;
}
void ICACHE_RAM_ATTR handleButtonPress2() {
buttonPressed2 = true;
}
void ICACHE_RAM_ATTR handleButtonPress3() {
buttonPressed3 = true;
}
void ICACHE_RAM_ATTR handleButtonPress4() {
buttonPressed4 = true;
}
void sendMessage(const char* message) {
if (!client.connect(serverIP, serverPort:) {
Serial.println("Connection failed");
return;
}
client.println(message);
client.flush();
//client.stop(); !!! эту строчку я отключил для тестов
Serial.println("Message sent");
}
void setup() {
Serial.begin(115200);
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(buttonPin3, INPUT_PULLUP);
pinMode(buttonPin4, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin1), handleButtonPress1, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonPin2), handleButtonPress2, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonPin3), handleButtonPress3, FALLING);
attachInterrupt(digitalPinToInterrupt(buttonPin4), handleButtonPress4, FALLING);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.println("IP address:");
Serial.println(WiFi.localIP:));
}
void loop() {
if (buttonPressed1) {
while (digitalRead(buttonPin1) == LOW) {
sendMessage("4");
}
buttonPressed1 = false;
}
if (buttonPressed2) {
while (digitalRead(buttonPin2) == LOW) {
sendMessage("6");
}
buttonPressed2 = false;
}
if (buttonPressed3) {
while (digitalRead(buttonPin3) == LOW) {
sendMessage("8");
}
buttonPressed3 = false;
}
if (buttonPressed4) {
while (digitalRead(buttonPin4) == LOW) {
sendMessage("2");
}
buttonPressed4 = false;
}
}


import socket
import keyboard
import time

def process_message(message):
# Преобразования сообщения в виртуальное нажатие клавиши

if message == "4":
keyboard.press("4")
# time.sleep(1) !!! Убрал все задержки
keyboard.release("4")

elif message == "6":
keyboard.press("6")
# time.sleep(1)
keyboard.release("6")

elif message == "8":
keyboard.press("8")
# time.sleep(1)
keyboard.release("8")

elif message == "2":
keyboard.press("2")
# time.sleep(1)
keyboard.release("2")

else:
print("Неизвестная команда")

def main():
host = "0.0.0.0"
port = 8888

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind:(host, port:)
server_socket.listen(1)

print("Server started. Waiting for connections...")

while True:
client_socket, client_address = server_socket.accept()
print("Connection accepted from:", client_address)

while True:
data = client_socket.recv(1024)
if not data:
break

message = data.decode("utf-8")
print("Received message:", message)

process_message(message)

client_socket.close()
print("Client disconnected.")

# Очистка буфера
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

if __name__ == "__main__":
main()
 

Вложения

  • controller_universal.zip
    1.7 KB · Просмотры: 3
Может кому-нибудь будет интересно...

 
Сверху Снизу
Обнаружен блокировщик рекламы AdBlock

МЫ ДОГАДЫВАЕМСЯ, ЧТО РЕКЛАМА ВАС РАЗДРАЖАЕТ!

Конечно, Ваше программное обеспечение для блокировки рекламы отлично справляется с блокировкой рекламы на нашем сайте, но оно также блокирует полезные функции. Мы стараемся для Вас и не обязываем Вас донатить и скидывать денег на наши кошельки, чтобы пользоваться форумом, но реклама это единственное, что позволяет поддерживать проект и развивать его.

Спасибо за Ваше понимание!

Я отключил свой AdBlock    Нет, я не буду ничего отключать