Arduino Nano + Enc28j60 помощь новичку

Slitok
Offline
Зарегистрирован: 16.11.2015

Здраствуйте!

Требуется помощь в освоении девайсов из названия темы. Начальник поставил задачу освоить и выполнить проект, включающий в себя доступ к Arduino через сеть без прямого подключения к компьютеру по USB. Доступ осуществляется посредством  Web-браузера и на странице устройства помимо текста и картинки должны присутствовать 1 Combo-box, 2 Edit-box и две кнопки: "Применить" и "Сохранить".

Кнопка "Применить" выводит указанные целые значения в Edit-box на цифровые каналы посредством коротких импульсов. Кнопка "Сохранить" должна обеспечивать сохранение во внутренней энергонезависимой памяти Arduino значения из Combo-box и Edit-box.

На настоящем этапе удалось подружить Nano и Enc28j60. Позагружал несколько образцов скетчей. Даже попытался написать свой согласно параметрам задачи, но из-за объема текста на странице кончилась память. (((

Хочется не только выполнить задачу, но и разобраться с устройством, поскольку, думаю, мне еще придется с ним столкнуться. С чего начать и куда копать? Для начала нужна "нарядная" web-страница с указанными элементами.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Да...

Начальник - зверь!

 

P.S. А вы случайно не художник-оформитель?

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Данное сочетание подошлобы для работы по UDP протоколу - с четко формированными пакетами данных. WEB не потащит -  как я понял вы в этом уже убедились. Нужно что-то вроде Raspberry PI или Intel Edson

Slitok
Offline
Зарегистрирован: 16.11.2015

Gippopotam пишет:

Начальник - зверь!

P.S. А вы случайно не художник-оформитель?

Хорошо иронизировать, когда понимаешь суть. А я в этом не бум-бум. И не знаю с чего начать и куда приткнуться... Хотел вот здесь помощи поискать.

Slitok
Offline
Зарегистрирован: 16.11.2015

Не понимаю, почему не потащит... Судя по примерам проектов на этом сайте nano тащит гораздо более крутые разработки.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Slitok пишет:

Gippopotam пишет:

Начальник - зверь!

P.S. А вы случайно не художник-оформитель?

Хорошо иронизировать, когда понимаешь суть. А я в этом не бум-бум. И не знаю с чего начать и куда приткнуться... Хотел вот здесь помощи поискать.

Я иронизирую, т.к. достаточно поменять "начальник" на "преподаватель" и многое становится ясным.

Slitok
Offline
Зарегистрирован: 16.11.2015

Gippopotam пишет:

Я иронизирую

А лучше бы помогли. Задачу поставил именно "начальник". Я не могу знать откуда в его старой голове появилась такая идея. (((

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Slitok пишет:

А лучше бы помогли.

Хорошо, начну с совета, выбросить Enc28j60.

Если жалко выбрасывать - посмотрите в соседнюю тему:
http://arduino.ru/forum/proekty/web-server-na-arduino-s-kontrollerom-temperatury

 

Цитата:

Задачу поставил именно "начальник". Я не могу знать откуда в его старой голове появилась такая идея. (((

А почему именно вас попросил сделать, а не меня, например? Какая разница, кому платить?

Slitok
Offline
Зарегистрирован: 16.11.2015

Выкинуть? А как мне обосновать и чем заменить?

Платит не начальник, а организация. ))) Это не в компетенции нач.лаба. Но зато в его компетенции вот таким нехитрым способом озадачить своего сотрудника. (((

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Slitok пишет:

Выкинуть? А как мне обосновать и чем заменить?

Платит не начальник, а организация. ))) Это не в компетенции нач.лаба. Но зато в его компетенции вот таким нехитрым способом озадачить своего сотрудника. (((

Заменить на w5100.

Потом открыть примеры из библиотеки ETHERNET и разобраться, как оно работает.

Можете попробовать Ардуино Мега Сервер.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Изучите тут, все уроки и будет Вам щастие.

http://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/

забудьте про Enc28j60, только W5100 и понадобится SD.

В память так и будете упираться, пока не станете загружать страницу с SD, и обслуживать ее Ajax. Да и в этом случае, при большом объеме передаваемых данных можно упереться в память формироваруя XML отклик.

Тут работающий пример для Ajax на W5100. обратите внимание на пин для принудительного ресета W5100.

Тут сделанное из него на базе mega2560+W5100+часы+DS18B20, кнопки не на аяксе пока. Html код панели можете позаимствовать :)

Nano для разработки не удобна - мало оперативы, разрабатывайте на Mega2560, потом оптимизируйте и вклячивайте в nano, если влезет.

Для начала с кривой/косой web страницой научитесь манипулировать данными. Нарисовать страницу дело 25-е.

 

 

Slitok
Offline
Зарегистрирован: 16.11.2015

Спасибо! Вроде бы обосновал. Заказали указанные вами девайсы. Но задача пока осталась. С вашей помощью на сегодняшний момент удалось сделать требуемый вид страницы.

Теперь уперся в то, как обработать нажатие кнопки "Применить", чтобы она "выдирала" значения "Типа", "Канала1", "Канала2" и сохраняла их в EEPROM. Можете помочь строчкой кода?

P.S. Можно элемент "Группа" ограничить там, где красная линия на рисунке?

#include <EtherCard.h> 
#include <EEPROM.h> 

static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; 
static byte myip[] = { 192,168,1,203 }; 

const int ledPin =  6;      // the number of the LED pin

int ledState = LOW;             // ledState used to set the LED
byte Mode;

int ch1;
int ch2;

char chValue[4];

byte Ethernet::buffer[1000]; //        if you increase the size of the HTML code you may need to increase the buffer size (or it will stop working) //TODO
BufferFiller bfill;



void setup() 
{
  pinMode(ledPin, OUTPUT);

  Mode = EEPROM.read(0);
  ch1 = EEPROM.read(1);
  ch2 = EEPROM.read(2);

  Serial.begin(9600);
  
  if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0)
    Serial.println(F("Failed to access Ethernet controller"));
  ether.staticSetup(myip);

}

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"
    "<!DOCTYPE html>"
    "<html><head>"
    "<meta http-equiv='refresh' content='60'/>"
    "<meta charset='utf-8'>"
    "<title>Ввод задержек</title>"
    "<body>"
    
    "<left><font size=\"4\">"
    "<form><fieldset><legend><strong>Ввод задержек</strong></legend>"
    "<p><strong>Тип:</strong><input type=radio name=mode value=1 checked=checked> 1мкс <input type=radio name=mode value=10> 10нс </p>";
    
const char http_Button[] PROGMEM =
    "<p><input type=submit value='   Применить   '> <input type=submit value='   Сохранить   '></p></fieldset></form>";

 
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>";



static word homePage() {
  bfill.emit_p(http_OK);

  bfill.emit_p(PSTR("<p><strong>Канал 1:</strong> <input type=number size=3 name=ch1 min=1 max=100 value=$D></p>"), ch1);
  bfill.emit_p(PSTR("<p><strong>Канал 2:</strong> <input type=number size=3 name=ch2 min=1 max=100 value=$D></p>"), ch2);

  bfill.emit_p(http_Button);

  
  return bfill.position();
}

void loop () 
{
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  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();
          	}


          //digitalWrite(ledPin, HIGH);
       }
        
      
       ether.httpServerReply(bfill.position());
    }
  
}

 

Slitok
Offline
Зарегистрирован: 16.11.2015

Если найдете что-то неверное в коде, то исправления приветствуются!

Slitok
Offline
Зарегистрирован: 16.11.2015

inspiritus пишет:

Изучите тут, все уроки и будет Вам щастие.

http://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/

Интересное чтиво, спасибо! Жаль на работе Интернета нет. В оффлайне такого не найти? Учту ваши рекомендации.

Slitok
Offline
Зарегистрирован: 16.11.2015
Проект вышел на финишную прямую. Практически все задачи выполнил. Осталось решить
проблему с тем, что при максимально возможном значении параметров ch1 и ch2 (т.е. 65535)
функция SendCounter в строке 95 и 101 выполняется 2, а то и 3 раза. Видимо это из-за длительности
выполнения функции. Как мне заставить программу ограничиться только разовым исполнением?
Все флаги уже перепробовал... (((
 
#include <EtherCard.h> // Библиотека для сетевой карты
#include <EEPROM.h> // Библиотека энергонезависимой памяти
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; // MAC адрес
static byte myip[] = { 192,168,1,13 }; //IP адрес
const int ipPin = 2;
const int idPin = 5;
const int ledPin1 = 6;
const int ledPin2 = 7;
byte Mode;
unsigned int ch1 = 0;
unsigned int ch2 = 0;
byte ip[4];
char chValue[10];
byte Ethernet::buffer[1100]; //
if you increase the size of the HTML code you may need to increase
the buffer size (or it will stop working) //TODO
BufferFiller bfill;
void setup() {
pinMode(ipPin, INPUT);
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(idPin, INPUT);
if(digitalRead(idPin)== HIGH)Mode = 0; //идентификация устройства
else Mode = 1;
ch1 = EEPROM_uint_read(5);
ch2 = EEPROM_uint_read(9);
Serial.begin(9600);
for(int i = 0; i < 4; i++) {
myip[i] = EEPROM.read(i);
delay(50);}
}
if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0)
Serial.println(F("Failed to access Ethernet controller"));
ether.staticSetup(myip);
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"
"<!DOCTYPE html>""<html><head>"
"<meta http-equiv='refresh' content='15'/>"
"<meta charset='utf-8'>"
"<title>2-х канальная линия задержки</title>"
"<body>"
"<left><font size=\"4\">"
"<form><fieldset><legend><strong>Управление 2-х канальной линией
задержки</strong></legend>"
"<p>Заполните форму и нажмите кнопку <strong>'Применить'</strong></p>";
checked=checked> Тип 1 (10нс) <input type=radio name=mode value=10> Тип 2 (1мкс) </p>";
const char http_Button[] PROGMEM =
"<p><input type=submit name=apply value=' Применить '> </p></fieldset></form>";
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>";
static word homePage() {
bfill.emit_p(http_OK);
bfill.emit_p(PSTR("<p><strong>Канал 1 (мкс):</strong> <input type=text size=8 name=ch1
value=$D></p>"), ch1);
bfill.emit_p(PSTR("<p><strong>Канал 2 (мкс):</strong> <input type=text size=8 name=ch2
value=$D></p>"), ch2);
bfill.emit_p(http_Button);
return bfill.position();
}
void loop () {
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if(digitalRead(ipPin)== HIGH){
EEPROM.write(0, 192);
EEPROM.write(1, 168);
EEPROM.write(2, 1);
EEPROM.write(3, 13);
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();
}
else if(ether.findKeyVal(data + 1, chValue , sizeof chValue , "apply") > 0)
{
if (ether.findKeyVal(data + 1, chValue , sizeof chValue , "ch1") > 0)
{
ch1 = atoi(chValue);
EEPROM_uint_write(5,ch1);
ch1 = SendCounter(ch1, Mode,ledPin1);
}
if (ether.findKeyVal(data + 1, chValue , sizeof chValue , "ch2") > 0)
{
ch2 = atoi(chValue);
EEPROM_uint_write(9,ch2);
ch2 = SendCounter(ch2, Mode,ledPin2);
}
bfill.emit_p(http_Found);
}
}
}
}
ether.httpServerReply(bfill.position());
//счетчик
unsigned int SendCounter (unsigned int num, byte mode, int pin){
unsigned int counter;
//если квант 1мкс
if(mode==1){
counter = num;
for(unsigned int i=0; i<counter; i++){
digitalWrite(pin, HIGH);
digitalWrite(pin, LOW);
}
}
}
//если квант 10нс
else{
counter = num*100;
for(unsigned int i=0; i<counter; i++){
digitalWrite(pin, HIGH);
digitalWrite(pin, LOW);
}
}
return counter;
// чтение
unsigned int EEPROM_uint_read(int addr) {
byte raw[2];
for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);unsigned int &num = (unsigned int&)raw;
return num;
}
// запись
void EEPROM_uint_write(int addr, unsigned int num) {
byte raw[2];
(unsigned int&)raw = num;
for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}

 

 

Slitok
Offline
Зарегистрирован: 16.11.2015

Gippopotam, поможете закончить?

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Slitok пишет:

Gippopotam, поможете закончить?

А чё я-то?

Я честно пытался понять что оно у вас делает - не смог.

Slitok
Offline
Зарегистрирован: 16.11.2015

Берет два числа из 2-х edit-box и отправляет по 2-м заданным цифровым выходам указанное кол-во импульсов. Но только при числе 65535, т.е максимальном делает это 2 раза, что нехорошо.