Отправить строку через текстовое поле веб-сервера без использования SD-карты?

Со времени моего последнего постая пытался сделать кое-что еще с моим проектом Stranger Things Wall.

Я подключил жидкокристаллический экран (16x2), который выводит любой обрабатываемый текст на стену и показывает, что пишется (чтобы мы могли прочитать полное сообщение, даже если мы потеряли первые мигающие символы).

В исходном примере, которому я следовал, для отправки сообщения использовалось приложение Bluetooth, однако я хочу использовать веб-сервер с Ethernet.

Моя текущая задача заключается в том, можно ли создать веб-сервер для передачи текста на arduino без использования SD-карты. Мне удалось найти пример, который отправляет простую команду, но в моем случае мне нужно вызвать функцию и отправить строку.

Мои знания ограничены в области HTML и JS, поэтому любая помощь приветствуется. Если это имеет значение, то Ethernet Shield, который я использую в настоящее время, - это W5100.

Схема такая же, как и в предыдущем посте, однако вот обновленный код:

#include <Wire.h> //INCLUSÃO DE BIBLIOTECA
#include <LiquidCrystal_I2C.h> // INCLUSÃO DE BIBLIOTECA
#include <SPI.h> //INCLUSÃO DE BIBLIOTECA
#include <Ethernet.h> //INCLUSÃO DE BIBLIOTECA

//Вывод, подключенный к ST_CP 74HC595
#define latchPin 5
//Контакт, подключенный к SH_CP 74HC595
#define clockPin 7
////Контакт, подключенный к DS 74HC595
#define dataPin 6
// размер буфера, используемого для захвата HTTP-запросов
#define REQ_BUF_SZ   90
// размер буфера, в котором хранится строка текста для ЖК-дисплея + нулевой терминатор
#define LCD_BUF_SZ   17
char HTTP_req[REQ_BUF_SZ] = {0}; // буферизованный HTTP-запрос, сохраненный как строка с нулевым завершением
char req_index = 0;              // индекс в буфер HTTP_req
LiquidCrystal_I2C lcd(0x27,16,2);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //АТРИБУТ КОНЕЧНОГО MAC AO ETHERNET SHIELD W5100 - ETIQUETINHA
EthernetServer server(80);
String text;                                                    //Variável do tipo string que receberá o texto

void setup() {
  Serial.begin(9600);                                           //Скорость связи
  for (int i = 2; i < 7; i++) {
    if (i != 4) {
      pinMode(i, OUTPUT);                                   //Declarando o pino como saída
    }
  }
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  lcd.init();
  lcd.setBacklight(HIGH);
  lcd.setCursor(0,0);
  lcd.print("Iniciando");
  if (Ethernet.begin(mac) == 0) {
    lcd.clear();
    lcd.setCursor(1,0);
    lcd.print("FALHA AO PEGAR");
    lcd.setCursor(7,1);
    lcd.print("IP");
  // нет смысла продолжать, так что больше ничего не делай:
    delay(5000);
    return;
  }
  // выведите свой локальный IP-адрес:
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("PRONTO");
  lcd.setCursor(0,1);
  lcd.print(Ethernet.localIP());
  server.begin(); 
  brilho(255);
  inicializationEffect();                                       //Chamada da Função responsável pelo efeito inicial
}
void loop() {
   EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // http-запрос заканчивается пустой строкой
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // если вы дошли до конца строки (получили новую строку
        // символ) и строка пуста, http-запрос завершен,
        // так что вы можете отправить ответ
        if (c == '\n' && currentLineIsBlank) {
          // отправить стандартный заголовок HTTP-ответа
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // соединение будет закрыто после завершения ответа
          client.println("Refresh: 5");  // обновляйте страницу автоматически каждые 5 секунд
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<h2>Stranger Things</h2><br />");
          client.println("</HTML>");
          break;
        }
        if (c == '\n') {
          // ты начинаешь новую линию
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // вы получили символ в текущей строке
          currentLineIsBlank = false;
        }
      }
    }
    // дайте веб-браузеру время для получения данных
    delay(1);
    // закрыть соединение:
    client.stop();
    Serial.println("client disconnected");
  }
   
  //receiveText();                                               //Chamada da função responsável por receber o texto digitado
}
//Função que recebe o texto diitado
void receiveText() {
  while (Serial.available() > 0) {                              //Verifica se existe alguma informação na Serial
    char c = Serial.read();                                     //atribui cada caractere a variável c que é do tipo char
    if (c != '\n') text.concat(c) ;                              //verifica se a variável do tipo char recebeu uma quebra de linha que indica o fim da palavra ou frase e concatena todos os caracteres na String text
    delay(10);                                                  //aguarda 10 milissegundos
  }
  if (text.length() > 0) {                                      //проверка текста строки тем tamanho maior que 0
    text.toUpperCase();                                       //transforma tudo que estiver na string text para maiúsculo
    if (text[0]=='#'){
      waveEffect();
    }else if(text[0]=='!'){
      blink();
    }else {
      executeEffect(text);                                        //chama a função executeEffect передает строковый текст с параметрами
    }
  }
  text = "";                                                    //лимпа строковый текст
}
//Função responsável por ativar linha que recebe como parâmetro o número da linha
void lineActivation(int line, int keepalive) {
  if (keepalive == 0) {
    for (int i = 2; i <= 4; i++) {
      if (i == 4) { i = 8; } //porta 4 usada pelo SD делать Ethernet
      digitalWrite(i, LOW);
    }
  }
  if (line >= 1 && line <=3){
    if (line == 3) { line = 7; } //porta 4 usada pelo SD делать Ethernet
    digitalWrite(line+1, HIGH);                               //coloca a linha 1 em estado lógico alto
  }
}

void activateLetter(char letter, int on, int off) {
  int lt;
  brilho(255);
  lt = (((int)letter - 64) % 9);
  if (((int)letter - 64) > 8) {
    lt = lt + 1;
  }
  if (on) {
    callCol(1<<lt-1);
    delay(on);                                                //mantém o pino em nível lógico alto durante o tempo que foi determinado no parâmetro da função
  }
  if (off) {
    callCol(0);
    delay(off);                                               //mantém o pino em nível lógico baixo durante o tempo que foi determinado no parâmetro da função
  }

}

void callCol(int col){
  digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, highByte(col));  
shiftOut(dataPin, clockPin, MSBFIRST, lowByte(col));  
  digitalWrite(latchPin, HIGH);

}
void executeEffect(String text) {
  for (int i = 0; i < text.length(); i++) {
    if (text[i] == ' ') {
      delay(1000);
    } else if ((int)text[i] < 65 or (int)text[i] > 90) {
    } else {
      lineActivation(int(((int)text[i] - 64) / 9) + 1, 0);
      activateLetter(text[i], 1000, 200);
    }
  }
}

void inicializationEffect() {
  for (int i = 1; i < 27; i++) {
    lineActivation(int(i / 9) + 1, 0);                          //ativa a linha
    activateLetter(char(64 + i), 100, 10);                   //ativa a letra
  }
}
void waveEffect() {
  Serial.println("Wave");
  for (int i = 1; i < 4; i++) {
    lineActivation(i, 1);                          //ativa a linha
  }
  for (int i = 1; i < 10; i++) {
    activateLetter(char(72 + i), 100, 0);
  }

  for (int i = 1; i < 10; i++) {
    activateLetter(char(72 + i), 0, 100);
  }
    lineActivation(0, 0);                          //ativa a linha
  
}
void blink() {
  Serial.println("Blink");
  callCol(511);
  lineActivation(1,1);
  lineActivation(2,1);
  lineActivation(3,1);
  for (int i = 0; i < 256; i++){
    brilho(i);
    delay(1);
  }
  delay(100);
  for (int i = 255; i >= 0; i--){
    brilho(i);
    delay(1);
  }
}

void brilho(byte brt) { // от 0 до 255
  analogWrite(9, 255-brt);
}

, 👍0

Обсуждение

ваш код не имеет функций SD - карты ... непонятно, о чем вы спрашиваете, @jsotola

ДА. У меня нет функций SD-карты, и я не собираюсь их использовать. Я хотел бы знать, возможно ли выполнить команду "On press отправить код процесса" без SD-карты. Каждый пример, который я нашел до сих пор, требует SD-карты и использует Ajax / js или что-то связанное., @Feeds

Вы можете создать простой веб-сервер для Arduino и создать HTML-страницу в качестве пользовательского интерфейса для отправки команд в Arduino из веб-браузера. Если вы хотите пройти весь путь, вы даже можете разместить на Arduino эту веб-страницу и обмениваться данными через websocket, если вы сможете разместить все это в памяти Arduino Uno. Я реализовал такую вещь, так что это выполнимо, но это было на Arduino Nano 33 IoT. Кстати, я не понимаю, какое отношение к этому имеет SD-карта., @ocrdu

я уверен, что вы можете найти минимальный код ajax, который не хранит файлы javascript локально .... ваша проблема в том, что вы ищете в области arduino... ответы находятся в области html / javascript / ajax ... ваш вопрос на самом деле не об arduino, @jsotola

Я понимаю, так что это неподходящее место, чтобы задавать такой вопрос. Должен ли я удалить его или оставить в силе и дождаться завершения голосования? Проблема с SD заключается только в том, что я могу найти только примеры, которые работают непосредственно на SD, @Feeds

Ну, вам нужно запустить веб-сервер на Arduino, этот бит принадлежит здесь, и вопросы о создании веб-интерфейса для управления Arduino меня не так сильно беспокоят, но мнения сильных мира сего могут отличаться., @ocrdu

Что ж, пока я буду продолжать в том же духе, и если каким-то образом я получу решение, я сам отвечу на него, он остается открытым., @Feeds


1 ответ


Лучший ответ:

2

Да, и это не так уж сложно, но нужно ли вам выполнять синтаксический анализ строк на языке Си, чтобы достичь этого?

В своем коде вы байт за байтом считываете заголовок HTTP-запроса и отправляете его в serial, по сути отбрасывая его.

Вместо этого вам нужно прочитать заголовок построчно (по крайней мере, первую строку) и проанализировать параметры URL.

Формат первой строки должен быть примерно таким:

GET / HTTP/1.1

или:

GET /?text=This+will+be+displayed HTTP/1.1

Вам нужно проанализировать это, чтобы получить все между = и пробелом, если они существуют. Затем вы можете отобразить его по своему усмотрению.

Далее вам также необходимо изменить код, который отправляет содержимое веб-страницы, чтобы он также включал простую HTML-форму с методом GET и назначением /, которая содержит текстовое поле с именем text.

,

Я последовал вашей идее и, погуглив о том, как обращаться с результирующими строками, нашел ваши примеры того, как использовать массив символов вместо строки. Это сработало очень хорошо! Спасибо! Я также последовал вашему ответу, чтобы преобразовать%20 в пробел и так далее, но застрял на проблеме с акцентированными буквами, потому что некоторые символы превышают 127 (например, Â), но, думаю, я просто не забуду их использовать., @Feeds

@Feeds Акценты - неприятная тема. Не существует стандарта для того, как подогнать их к 8-битным значениям, и каждый язык имеет свое собственное расположение. Вот почему был создан UTF. И это становится * действительно * неприятным для анализа, поскольку существует несколько стандартов UTF..., @Majenko