Arduino nano и enc28j60

kuzmich9023
Offline
Зарегистрирован: 19.12.2014

Привет всем кто не прошёл мимо. Есть код переделанный под свою задачу(он ниже). В нём у меня не получается вывести значения переменной santimetr в веб. При работе там всегда значение 0, в тоже самое время в Serial всё отлично пишется.


#include <EtherCard.h>  // Подключаем скачанную библиотеку. https://yadi.sk/d/R57sVoglbhTRN
#include <EEPROM.h> // Для  Записи / восстановление из EEPROM состояния LedPins.
#define FLOATEMIT

 
static byte mymac[] = {0x74,0x69,0x69,0x2D,0x30,0x31};//74-69-69-2D-30-31
static byte myip[] = {192,168,0,203};//IP 192.168.0.203
byte Ethernet::buffer[1150];//1150Kb
BufferFiller bfill;
int LedPins[] = {2,3,4,5};//,6,7,8,9};
boolean PinStatus[3];
//double Vrotator = 0.00;
const int SensorPin = 8;
int signal = 0;
int Counter = 0;//счётчик в ноль
double santimetr = 0.00;//дробная переменная показаний "ммилиметр"
double ost = 1.25;
int lastSignal = 0;

//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

const char http_OK[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n\r\n";

const char http_Found[] PROGMEM =
"HTTP/1.0 302 Found\r\n"
"Location: /\r\n\r\n";

const char http_Unauthorized[] PROGMEM =
"HTTP/1.0 401 Unauthorized\r\n"
"Content-Type: text/html\r\n\r\n"
"<h1>401 Unauthorized</h1>";



//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



// функция для оформления Web страницы. 
void homePage()
{//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 //int sensor0 = analogRead(A0);//сенсор на аналоговом входе "0" ардуино переменной sensor0 присваевается значение аналогового порта A0
 //int sensor1 = analogRead(A1);//сенсор на аналоговом входе "1" ардуино
                                                                       
 bfill.emit_p(PSTR("$F"
 // "<title>PIN Webserver </title>" 
    "VOSTOK 2: <a href=\"?VOSTOK2=$F\">$F</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp"
    "ZAPAD 3: <a href=\"?ZAPAD3=$F\">$F</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp"
    "VVERH 4: <a href=\"?VVERH4=$F\">$F</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp"
    "VNIZ 5: <a href=\"?VNIZ5=$F\">$F</a>"),
 
  http_OK,

  PinStatus[0]?PSTR("off"):PSTR("on"),
  PinStatus[0]?PSTR("<font color=\"green\"><b>&#9668</b></font>"):PSTR("<font color=\"red\">OFF</font>"),//надпись в вебсервере цветом зелёный "ON",цветом красный "OFF" 
  PinStatus[1]?PSTR("off"):PSTR("on"),
  PinStatus[1]?PSTR("<font color=\"green\"><b>&#9658</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[2]?PSTR("off"):PSTR("on"),
  PinStatus[2]?PSTR("<font color=\"green\"><b>&#9650</b></font>"):PSTR("<font color=\"red\">OFF</font>"),
  PinStatus[3]?PSTR("off"):PSTR("on"),
  PinStatus[3]?PSTR("<font color=\"green\"><b>&#9660</b></font>"):PSTR("<font color=\"red\">OFF</font>"));
 
bfill.emit_p(PSTR("<meta http-equiv='refresh' content='1'charset='utf-8'/>"
                  "<h1>&nbsp;&nbsp;&nbspГрадус=$D</h1>"), santimetr);//здесь по идее должны показывать значения миллиметров
}//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



//------------------------



void setup()
{
  Serial.begin(9600);
  if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0);
  if (!ether.dhcpSetup()); 
  ether.staticSetup(myip);
  for(int i = 0; i <= 7; i++)
  {
    pinMode(LedPins[i],OUTPUT); // весь массив LedPins делаем OUTPUT.
    PinStatus[i]=EEPROM.read(i); // Перезаписываем значения массива PinStatus, значениями из EEPROM.
    digitalWrite(LedPins[i],PinStatus[i]); // Восстанавливаем прошлое состояние LedPins.  
  }
pinMode(8, INPUT);
}

// --------------------------------------

void loop()
{

  signal = digitalRead(SensorPin); // пример->>> if ((RotationCount%9)==0) Serial.println("Pulse 9 times");
   if (signal != lastSignal)
 {
   if (signal == HIGH)
 {
   Counter++;
   if ((Counter%3)==0) 
   //Serial.println(santimetr=santimetr+ost);//выводит показания в миллиметрах
   santimetr = santimetr + ost;//выводит показания в миллиметрах
Serial.println(santimetr);
 }
   lastSignal = signal;
 }

  word len = ether.packetReceive();   // check for ethernet packet / проверить ethernet пакеты.
  word pos = ether.packetLoop(len);   // check for tcp packet / проверить TCP пакеты.

  if (pos) {
    bfill = ether.tcpOffset();
    char *data = (char *) Ethernet::buffer + pos;
    if (strncmp("GET /", data, 5) != 0) {
      bfill.emit_p(http_Unauthorized);
    }
    else {

      data += 5;
      if (data[0] == ' ') {       
        homePage(); // Return home page, Если обнаружено изменения на станице, запускаем функцию.
        // for (int i = 0; i <= 7; i++)digitalWrite(LedPins[i],PinStatus[i]);                              
        // EEPROM.write(i,PinStatus[i]);delay(10);Serial.println(1);

      }


      // "16" = количество символов "?ArduinoPIN1=on ".
      else if (strncmp("?VOSTOK2=on ", data, 12) == 0) {
        PinStatus[0] = true; 
        digitalWrite(LedPins[0],PinStatus[0]); 
        EEPROM.write(0,PinStatus[0]); // записываем в ячейку EEPROM №0, текущее состояние LedPins[0].    
        bfill.emit_p(http_Found);
      }
      else if (strncmp("?ZAPAD3=on ", data, 10) == 0) {
        PinStatus[1] = true;
        digitalWrite(LedPins[1],PinStatus[1]); 
        EEPROM.write(1,PinStatus[1]);
        bfill.emit_p(http_Found);
      }
      else if (strncmp("?VVERH4=on ", data, 10) == 0) {
        PinStatus[2] = true;
        digitalWrite(LedPins[2],PinStatus[2]); 
        EEPROM.write(2,PinStatus[2]);
        bfill.emit_p(http_Found);
      }
      else if (strncmp("?VNIZ5=on ", data, 10) == 0) {
        PinStatus[3] = true;
        digitalWrite(LedPins[3],PinStatus[3]); 
        EEPROM.write(3,PinStatus[3]);
        bfill.emit_p(http_Found);
      }
  



      //------------------------------------------------------  



      else if (strncmp("?VOSTOK2=off ", data, 12) == 0) {
        PinStatus[0] = false; 
        digitalWrite(LedPins[0],PinStatus[0]); 
        EEPROM.write(0,PinStatus[0]);       
        bfill.emit_p(http_Found);
      }
      else if (strncmp("?ZAPAD3=off ", data, 11) == 0) {
        PinStatus[1] = false; 
        digitalWrite(LedPins[1],PinStatus[1]);  
        EEPROM.write(1,PinStatus[1]);      
        bfill.emit_p(http_Found);
      }
      else if (strncmp("?VVERH4=off ", data, 11) == 0) {
        PinStatus[2] = false; 
        digitalWrite(LedPins[2],PinStatus[2]); 
        EEPROM.write(2,PinStatus[2]);       
        bfill.emit_p(http_Found);
      }
      else if (strncmp("?VNIZ5=off ", data, 11) == 0) {
        PinStatus[3] = false; 
        digitalWrite(LedPins[3],PinStatus[3]); 
        EEPROM.write(3,PinStatus[3]);       
        bfill.emit_p(http_Found);
      }
 
      else {
        // Page not found
        bfill.emit_p(http_Unauthorized);
      }
    }
    ether.httpServerReply(bfill.position());    // send http response
  }
}








 

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

Посмотрите на свои строки 66-67

bfill.emit_p(PSTR("<meta http-equiv='refresh' content='1'charset='utf-8'/>" 
           "<h1>&nbsp;&nbsp;&nbspГрадус=$D</h1>"), santimetr);//здесь по идее должны показывать значения миллиметров

По какой это такой идее она должна показывать плавающее число (santimetr описано как double), если Вы задали формат $D, который означает "целое число"?

Ни по какой идее не должно!

Напишите правильный формат $T и включите поддержку плавающей точки. Для этого найдите в файле EtherCard.cpp строку 

//#define FLOATEMIT // uncomment line to enable $T in emit_P for float emitting

(у меня она 16-ая) и раскомментируйте её.

Но более правильно - постараться обойтись без плавающей точки. Она Вам здесь реально не нужна, а память жрёт за милую душу.

kuzmich9023
Offline
Зарегистрирован: 19.12.2014

Благодарю за подсказку. Всё сделал как вы написали и как итог получилось. Я не силён в HTML поэтому затык был. Вот маленький вопрос к вам как специалисту данного сектора. Сейчас у меня выводится Градус=12.500 ,а как последний ноль убрать? И где прочесть про типы данных HTML используемого в ардуине?

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

kuzmich9023 пишет:

Сейчас у меня выводится Градус=12.500 ,а как последний ноль убрать?

Ищете в файле EtherCard.cpp строку

dtostrf    (    va_arg(ap, double), 10, 3, (char*)ptr );

у меня она 288. И изменяеете параметры функции dtostrf. Здесь 10 - это общая ширина поля под число (включая десятичную точку), 3 - количество знаков после запятой, см. описание dtostrf

kuzmich9023 пишет:

И где прочесть про типы данных HTML используемого в ардуине?

Всё, о чём мы говорим никак не относится к HTML. Это чисто С-шные штучки. Где читать описание возможностей  библиотеки EtherCard я не знаю, т.к. никогда особо нужно не было. То, что я Вам сейчас говорю я нигде не читал, просто посмотрел на текст библиотеки.

kuzmich9023
Offline
Зарегистрирован: 19.12.2014

Хорошо что вы разъяснили как и с чем. Я догадывался про прожорливость кода и спользованием плавающей точки.

Вот уже в программе видны некоторые тормоза с её применением. В планах было использовать два параллельных вычисления с использованием float, а тут ещё и сама библиотека EtherCard жрёт оперативу. Вообщем спасибо за помощь в решении вопроса,но мне пришлось отказаться от затеи с управлением моим устройством через Web и перейти на использование двух ардуин с использованием RS-485/422связи между ними.

sadman41
Offline
Зарегистрирован: 19.10.2016

Для ENC28J60 есть еще один драйвер - UIP Ethernet, он, как пишут, более экономный по памяти. Или берите W5100 - классический вариант для Ethernet на Arduino. 

kuzmich9023
Offline
Зарегистрирован: 19.12.2014

Благодарю за советы. Я уже думал изначально по поводу W5100 и даже заказал на Ali, но вот пока платы ехали я пересмотрел реализацию идеи. Открываются реали про ENC28J60 и на ней как выходит если многофункционально то контроллер мощный с оперативой или урезанный веб. Пока остановился на rs422 и вроде получается задуманное. 485 не подошёл по реализации тк дуплекс нужен.

Всем огромное спаибо кто участвовал в обсуждении данного вопроса.