Странное поведение программы.

ToT
Offline
Зарегистрирован: 25.08.2017

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

Код:

#include <SPI.h>
#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,11,11 };

byte Ethernet::buffer[600];
BufferFiller bfill;

// Массив задействованных номеров Pins Arduino, для управления например 8 реле.
int LedPins[] = {
  2,3,4,5};
 
// Массив для фиксации изменений.
boolean PinStatus[] = {
  false,false,false,false};
 
//-------------
 
const char http_OK[] PROGMEM =
"<!DOCTYPE HTML><html><head></head><body>";
 
const char http_Found[] PROGMEM =
"";
 
 
// задаем переменные для клиента:
char linebuf[80];
int charcount=0;
 
void setup() {
  // подготавливаем реле-модуль:
  for(int i = 0; i < 4; i++)
  {
  pinMode(LedPins[i],OUTPUT); 
  digitalWrite(LedPins[i], HIGH);
  PinStatus[i]=false;
  }  
 
  // открываем последовательную коммуникацию на скорости 9600 бод:
  Serial.begin(9600);
 
  // запускаем Ethernet-коммуникацию и сервер:
  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0){
  Serial.println(F("Failed to access Ethernet controller"));
  }else{
  ether.staticSetup(myip);
  ether.printIp("My SET IP: ", ether.myip);
  }
}
 
// Показываем веб-страницу с кнопкой «вкл/выкл» для реле:
void homePage() {
  bfill.emit_p(PSTR(
  "<!DOCTYPE HTML><html><head></head><body>"
  "<title>ArduinoPIN Webserver</title>" 
  "ArduinoPIN 1: <a href=\"?ArduinoPIN1=$F\">$F</a><br />"
  "ArduinoPIN 2: <a href=\"?ArduinoPIN2=$F\">$F</a><br />"  
  "ArduinoPIN 3: <a href=\"?ArduinoPIN3=$F\">$F</a><br />"
  "ArduinoPIN 4: <a href=\"?ArduinoPIN4=$F\">$F</a>"
  "</body></html>"),   
  PinStatus[1]?PSTR("off"):PSTR("on"),
  PinStatus[1]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[2]?PSTR("off"):PSTR("on"),
  PinStatus[2]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[3]?PSTR("off"):PSTR("on"),
  PinStatus[3]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[4]?PSTR("off"):PSTR("on"),
  PinStatus[4]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"));
 }
 
 
void loop() {
  delay(1); // Дёргаем микроконтроллер.
 
  word len = ether.packetReceive();   // check for ethernet packet / проверить ethernet пакеты.
  word pos = ether.packetLoop(len);   // check for tcp packet / проверить TCP пакеты.
 
  if (pos) {
    bfill = ether.tcpOffset();
    Serial.println("new client");  //  "новый клиент"
    char *data = (char *) Ethernet::buffer + pos;
      data += 5;
  if (data[0] == ' ') {       
        homePage(); // Return home page Если обнаружено изменения на странице, запускаем функцию.
        for (int i = 0; i <= 3; i++)digitalWrite(LedPins[i],PinStatus[i]);
  }
    // "16" = количество символов "?ArduinoPIN1=on ".

    if (strncmp("?ArduinoPIN1=on ", data, 16) == 0) {
    PinStatus[1] = true;        
    }
    else if (strncmp("?ArduinoPIN2=on ", data, 16) == 0) {
    PinStatus[2] = true;        
     }
    else if (strncmp("?ArduinoPIN3=on ", data, 16) == 0) {
    PinStatus[3] = true;        
    }
    else if (strncmp("?ArduinoPIN4=on ", data, 16) == 0) {
    PinStatus[4] = true;        
     }
    
    //------------------------------------------------------  
 
 
    else if (strncmp("?ArduinoPIN1=off ", data, 17) == 0) {
    PinStatus[1] = false;        
    }
    else if (strncmp("?ArduinoPIN2=off ", data, 17) == 0) {
    PinStatus[2] = false;        
     }
    else if (strncmp("?ArduinoPIN3=off ", data, 17) == 0) {
    PinStatus[3] = false;        
     }
    else if (strncmp("?ArduinoPIN4=off ", data, 17) == 0) {
    PinStatus[4] = false;        
     }
  
  }
  ether.httpServerReply(bfill.position());    // send http response
    
}

Все типа запускается, но страница не открывается вместо открывания страницы браузер скачивает какую то кракозябу:
        L><html><head></head><body><title>ArduinoPIN Webserver</title>ArduinoPIN 1: <a href="?ArduinoPIN1=on"><font color="red">OFF</font></a><br />ArduinoPIN 2: <a href="?ArduinoPIN2=on"><font color="red">OFF</font></a><br />ArduinoPIN 3: <a href="?ArduinoPIN3=on"><font color="red">OFF</font></a><br />ArduinoPIN 4: <a href="?ArduinoPIN4=on"><font color="red">OFF</font></a></body></html>

То есть в начале страницы часть символов подменяется на последовательность "NULNULNULNULNULNULNULBSSOHSOHEOTSTXNUL"

Nosferatu
Offline
Зарегистрирован: 04.11.2012

Попробуйте удалить все переносы строк и пробелы перед html кодом.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
  bfill.emit_p(PSTR(
  "<!DOCTYPE HTML><html><head></head><body>"
  "<title>ArduinoPIN Webserver</title>" 
  "ArduinoPIN 1: <a href=\"?ArduinoPIN1=$F\">$F</a><br />"
  "ArduinoPIN 2: <a href=\"?ArduinoPIN2=$F\">$F</a><br />"  
  "ArduinoPIN 3: <a href=\"?ArduinoPIN3=$F\">$F</a><br />"
  "ArduinoPIN 4: <a href=\"?ArduinoPIN4=$F\">$F</a>"
  "</body></html>"),   
 }

Вы уверены что там надо много кавычек? Может хватит двух.

ToT
Offline
Зарегистрирован: 25.08.2017

Сделал, изменений к сожалению нет.

Код:

void homePage() {
  bfill.emit_p(PSTR(
"<!DOCTYPE HTML><html><head></head><body><title>ArduinoPIN Webserver</title> ArduinoPIN 1: <a href=\"?ArduinoPIN1=$F\">$F</a><br />ArduinoPIN 2: <a href=\"?ArduinoPIN2=$F\">$F</a><br />  ArduinoPIN 3: <a href=\"?ArduinoPIN3=$F\">$F</a><br />ArduinoPIN 4: <a href=\"?ArduinoPIN4=$F\">$F</a></body></html>"),   
  PinStatus[1]?PSTR("off"):PSTR("on"),
  PinStatus[1]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[2]?PSTR("off"):PSTR("on"),
  PinStatus[2]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[3]?PSTR("off"):PSTR("on"),
  PinStatus[3]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[4]?PSTR("off"):PSTR("on"),
  PinStatus[4]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"));
}

Все так же выводит NULL - ы.

Nosferatu
Offline
Зарегистрирован: 04.11.2012

ToT пишет:

Сделал, изменений к сожалению нет.

Код:

void homePage() {
  bfill.emit_p(PSTR(
"<!DOCTYPE HTML><html><head></head><body><title>ArduinoPIN Webserver</title> ArduinoPIN 1: <a href=\"?ArduinoPIN1=$F\">$F</a><br />ArduinoPIN 2: <a href=\"?ArduinoPIN2=$F\">$F</a><br />  ArduinoPIN 3: <a href=\"?ArduinoPIN3=$F\">$F</a><br />ArduinoPIN 4: <a href=\"?ArduinoPIN4=$F\">$F</a></body></html>"),   
  PinStatus[1]?PSTR("off"):PSTR("on"),
  PinStatus[1]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[2]?PSTR("off"):PSTR("on"),
  PinStatus[2]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[3]?PSTR("off"):PSTR("on"),
  PinStatus[3]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[4]?PSTR("off"):PSTR("on"),
  PinStatus[4]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"));
}

Все так же выводит NULL - ы.

Перенос строки остался в начале. Попробуйте объединить вторую и третью строку без переносов и пробелов.

Вообще если посмотреть результат в HTML коде, "Ctrl+U" в браузере, было бы понятней в каком месте копать.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Интересный у Вас комментарий в строке 75

 delay(1); // Дёргаем микроконтроллер.

За какое, интересно, место Вы его этой операцией дёргаете?

ToT
Offline
Зарегистрирован: 25.08.2017

Сделал как писали никаких отличий. :( Судя по всему изначальный пример был не очень рабочим.

Сделал все сначала. Страница заработала. Реле переключаются. Сервер ребутается.

Что было причиной косяка так и не разобрался.

Сейчас код:

#include <EtherCard.h>
#include <SPI.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,11 };
// Массив задействованных номеров Pins Arduino, для управления например 4 реле.
int LedPins[] = {
  2,3,4,5};
// Массив для фиксации изменений.
boolean PinStatus[4];
 

byte Ethernet::buffer[500];
BufferFiller bfill;
// задаем переменные для клиента:
char linebuf[180];
int charcount=0;

void setup () {
 // открываем последовательную коммуникацию на скорости 9600 бод:
  Serial.begin(9600);
  // запускаем Ethernet-коммуникацию и сервер:
  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println(F("Failed to access Ethernet controller"));
    ether.staticSetup(myip);

    ether.printIp("My SET IP: ", ether.myip);
  // подготавливаем реле-модуль:
  for(int i = 0; i < 4; i++)
  {
    pinMode(LedPins[i],OUTPUT); 
    digitalWrite(LedPins[i], HIGH);
    PinStatus[i]=false;
  }  
}

static word homePage() {
  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR(
    "<!DOCTYPE HTML><html><head></head>"
    "<body><title>ArduinoPIN Webserver</title>" 
    "ArduinoPIN 1: <a href=\"?ArduinoPIN1=$F\">$F</a><br />"
    "ArduinoPIN 2: <a href=\"?ArduinoPIN2=$F\">$F</a><br />"
    "ArduinoPIN 3: <a href=\"?ArduinoPIN3=$F\">$F</a><br />"
    "ArduinoPIN 4: <a href=\"?ArduinoPIN4=$F\">$F</a>"
    "</body></html>"),   
  PinStatus[0]?PSTR("off"):PSTR("on"),
  PinStatus[0]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[1]?PSTR("off"):PSTR("on"),
  PinStatus[1]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[2]?PSTR("off"):PSTR("on"),
  PinStatus[2]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[3]?PSTR("off"):PSTR("on"),
  PinStatus[3]?PSTR("<font color=\"green\"><b>ON</b></font>"):PSTR("<font color=\"red\">OFF</font>"));
  return bfill.position();
}

void loop () {
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  if (pos){  // check if valid tcp data is received
    Serial.println(pos);
    char *data = (char *) Ethernet::buffer + pos;
    data += 5;
    if (strncmp("?ArduinoPIN1=on ", data, 16) == 0) {
    PinStatus[0] = true;        
    }
    else if (strncmp("?ArduinoPIN2=on ", data, 16) == 0) {
    PinStatus[1] = true;        
    }
    else if (strncmp("?ArduinoPIN3=on ", data, 16) == 0) {
    PinStatus[2] = true;        
    }
    else if (strncmp("?ArduinoPIN4=on ", data, 16) == 0) {
    PinStatus[3] = true;        
    }
    
    //------------------------------------------------------  
 
 
    else if (strncmp("?ArduinoPIN1=off ", data, 17) == 0) {
    PinStatus[0] = false;        
    }
    else if (strncmp("?ArduinoPIN2=off ", data, 17) == 0) {
    PinStatus[1] = false;        
    }
    else if (strncmp("?ArduinoPIN3=off ", data, 17) == 0) {
    PinStatus[2] = false;        
    }
    else if (strncmp("?ArduinoPIN4=off ", data, 17) == 0) {
    PinStatus[3] = false;        
    }
      
    ether.httpServerReply(homePage()); // send web page data
    for (int i = 0; i <= 3; i++)digitalWrite(LedPins[i],PinStatus[i]);
  }
  delay(1);
}