Помогите, пожалуйста, со скетчем.
- Войдите на сайт для отправки комментариев
Ср, 18/11/2015 - 14:43
Первоисточник: http://arduino.ru/forum/proekty/web-server-na-arduino-s-kontrollerom-tem...
Взял последний скетч (на 4 датчика и реле), тупо добавил во все значения ещё по 4. Увеличил значение byte Ethernet::buffer до [7000] (ставил разные значения). Не работает. Скетч компилируется без ошибок, заливается в Мегу, но через браузер не отображается ничего. Не открывается страница. Кто может подсказать, где сказалась кривизна моих рук? Сразу сообщу, что я не силен в написании кода. Общую суть понимаю, а вот писать увы.
/*
* контроллер тёплого пола
*/
#include <EtherCard.h> // Библиотека для сетевой карты
#include <OneWire.h> // Бибилиотека для датчика температуты D18B20
#include <EEPROM.h> // Библиотека энергонезависимой памяти
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; // MAC адрес
const byte PinTemp = 9; // Датчики Dallas DS18B20 Temperature Sensors
const byte PinSSR1 = 3; // Реле Pin for SSR 1
const byte PinSSR2 = 4; // Реле Pin for SSR 2
const byte PinSSR3 = 5; // Реле Pin for SSR 3
const byte PinSSR4 = 6; // Реле Pin for SSR 4
const byte PinSSR5 = 7; // Реле Pin for SSR 5
const byte PinSSR6 = 8; // Реле Pin for SSR 6
const byte PinSSR7 = 22; // Реле Pin for SSR 7
const byte PinSSR8 = 23; // Реле Pin for SSR 8
//const byte pirPin = 1;
//Время, в которое был принят сигнал отсутствия движения(LOW)
//long unsigned int lowIn;
//long unsigned int pause = 0; //Пауза, после которой движение считается оконченным
//Флаг. false = значит движение уже обнаружено, true - уже известно, что движения нет
//boolean lockLow = true;
//Флаг. Сигнализирует о необходимости запомнить время начала отсутствия движения
//boolean takeLowTime;
char TargetTemperarureTextbox[10];
byte sensor1[8] = {0x00, 0xFF, 0xE0, 0x8C, 0x11, 0x14, 0x00, 0x6F}; // Адрес первого сенсора
byte sensor2[8] = {0x00, 0xFF, 0xAE, 0x92, 0x10, 0x14, 0x00, 0xA2}; // Адрес второго сенсора
byte sensor3[8] = {0x00, 0xFF, 0xC9, 0x4D, 0x11, 0x14, 0x00, 0xD2}; // Адрес третьего сенсора
byte sensor4[8] = {0x00, 0xFF, 0xE7, 0x8C, 0x11, 0x14, 0x00, 0x3E}; // Адрес четвертого сенсора
byte sensor5[8] = {0x28, 0x26, 0xBE, 0xC6, 0x02, 0x00, 0x00, 0x88}; // Адрес пятого сенсора
byte sensor6[8] = {0x28, 0x34, 0x96, 0xDD, 0x03, 0x00, 0x00, 0x7C}; // Адрес шестого сенсора
byte sensor7[8] = {0x28, 0x27, 0xBE, 0xC6, 0x03, 0x00, 0x00, 0x88}; // Адрес седьмого сенсора
byte sensor8[8] = {0x28, 0x34, 0x86, 0xDD, 0x00, 0x00, 0x00, 0x7C}; // Адрес восьмого сенсора
float temp1;
float temp2;
float temp3;
float temp4;
float temp5;
float temp6;
float temp7;
float temp8;
char chartemp1[10];
char chartemp2[10];
char chartemp3[10];
char chartemp4[10];
char chartemp5[10];
char chartemp6[10];
char chartemp7[10];
char chartemp8[10];
byte TargetTemp1;
byte TargetTemp2;
byte TargetTemp3;
byte TargetTemp4;
byte TargetTemp5;
byte TargetTemp6;
byte TargetTemp7;
byte TargetTemp8;
byte SSR1on = 0; // 0 is Off, 1 is On
byte SSR2on = 0; // 0 is Off, 1 is On
byte SSR3on = 0; // 0 is Off, 1 is On
byte SSR4on = 0; // 0 is Off, 1 is On
byte SSR5on = 0; // 0 is Off, 1 is On
byte SSR6on = 0; // 0 is Off, 1 is On
byte SSR7on = 0; // 0 is Off, 1 is On
byte SSR8on = 0; // 0 is Off, 1 is On
byte Ethernet::buffer[7000]; // 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;
OneWire ds(PinTemp); // пин подключения термодатчика
void setup () {
pinMode(PinTemp, INPUT);
pinMode(PinSSR1, OUTPUT); // sets the digital pin as input
pinMode(PinSSR2, OUTPUT); // sets the digital pin as input
pinMode(PinSSR3, OUTPUT); // sets the digital pin as input
pinMode(PinSSR4, OUTPUT); // sets the digital pin as input
pinMode(PinSSR5, OUTPUT); // sets the digital pin as input
pinMode(PinSSR6, OUTPUT); // sets the digital pin as input
pinMode(PinSSR7, OUTPUT); // sets the digital pin as input
pinMode(PinSSR8, OUTPUT); // sets the digital pin as input
TargetTemp1 = EEPROM.read(0);
TargetTemp2 = EEPROM.read(2);
TargetTemp3 = EEPROM.read(4);
TargetTemp4 = EEPROM.read(6);
TargetTemp5 = EEPROM.read(14);
TargetTemp6 = EEPROM.read(16);
TargetTemp7 = EEPROM.read(18);
TargetTemp8 = EEPROM.read(20);
ether.begin(sizeof Ethernet::buffer, mymac, 53);
ether.dhcpSetup();
}
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='120'/>"
"<meta charset='utf-8'>"
"<title>Тёплые полы</title>"
"<body>"
"<center><font size=\"4\">"
"<table border=\"1\" cellpadding=\"5\" style=\"width: 800px; border-collapse: collapse; border: 1px solid black;\">"
"<tr style=\"background-color: silver\"><td>Помещение:</td>"
"<td>Ванна</td>"
"<td>Прихожая</td>"
"<td>Зал</td>"
"<td>Кухня</td>"
"<td>Ванна2</td>"
"<td>Прихожая2</td>"
"<td>Зал2</td>"
"<td>Кухня2</td></tr>";
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>";
//$D = word data type
//$L = long data type
//$S = c string
//$F = progmem string
//$E = byte from the eeprom.
static word homePage() {
bfill.emit_p(http_OK);
bfill.emit_p(PSTR(
"<tr><td>Температура:</td>"
"<td>$S °C</td>"
"<td>$S °C</td>"
"<td>$S °C</td>"
"<td>$S °C</td>"
"<td>$S °C</td>"
"<td>$S °C</td>"
"<td>$S °C</td>"
"<td>$S °C</td></tr>"), chartemp1, chartemp2, chartemp3, chartemp4, chartemp6, chartemp6, chartemp7, chartemp8 );
bfill.emit_p(PSTR("<tr><td>Обогрев:</td>"));
if ( digitalRead(PinSSR1) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR2) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR3) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR4) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR5) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR6) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR7) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
if ( digitalRead(PinSSR8) == LOW ) {
bfill.emit_p(PSTR("<td><font color=green><b>ВКЛ</b></font></td>")); }
else {
bfill.emit_p(PSTR("<td><font color=red><b>ВЫКЛ</b></font></td>")); }
bfill.emit_p(PSTR("</tr><tr><td>Цель:</td>"));
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp1);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp2);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp3);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp4);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp5);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp6);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp7);
bfill.emit_p(PSTR("<td>$D °C</td>"), TargetTemp8);
bfill.emit_p(PSTR("</tr><tr><td>Установить:</td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp1 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp2 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp3 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp4 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp5 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp6 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp7 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("<td><form><input type=text name=ttemp8 size=10> <input type=submit value=ОК> </form></td>"));
bfill.emit_p(PSTR("</tr></table>"
"</font></center></body></html>"));
return bfill.position();
}
void loop(void) {
// if(analogRead(pirPin) > 500)
// {
// digitalWrite(PinSSR5, LOW);
// delay(50);
// }
// if(analogRead(pirPin) < 500)
// {
// digitalWrite(PinSSR5, HIGH);
// delay(50);
// }
// Serial.println(analogRead(pirPin));
temp1=tempread(sensor1);
dtostrf(temp1, 4, 2, chartemp1);
temp2=tempread(sensor2);
dtostrf(temp2, 4, 2, chartemp2);
temp3=tempread(sensor3);
dtostrf(temp3, 4, 2, chartemp3);
temp4=tempread(sensor4);
dtostrf(temp4, 4, 2, chartemp4);
temp5=tempread(sensor5);
dtostrf(temp5, 4, 2, chartemp5);
temp6=tempread(sensor6);
dtostrf(temp6, 4, 2, chartemp6);
temp7=tempread(sensor7);
dtostrf(temp7, 4, 2, chartemp7);
temp8=tempread(sensor8);
dtostrf(temp8, 4, 2, chartemp8);
if (temp1<TargetTemp1-0.5) {
digitalWrite(PinSSR1, LOW);
SSR1on = 1;
}
else if (temp1>TargetTemp1+0.5) {
digitalWrite(PinSSR1, HIGH);
SSR1on = 0;
}
if (temp2<TargetTemp2-0.5) {
digitalWrite(PinSSR2, LOW);
SSR2on = 1;
}
else if (temp2>TargetTemp2+0.5){
digitalWrite(PinSSR2, HIGH);
SSR2on = 0;
}
if (temp3<TargetTemp3-0.5) {
digitalWrite(PinSSR3, LOW);
SSR3on = 1;
}
else if (temp3>TargetTemp3+0.5){
digitalWrite(PinSSR3, HIGH);
SSR3on = 0;
}
if (temp4<TargetTemp4-0.5) {
digitalWrite(PinSSR4, LOW);
SSR4on = 1;
}
else if (temp4>TargetTemp4+0.5){
digitalWrite(PinSSR4, HIGH);
SSR4on = 0;
}
if (temp5<TargetTemp5-0.5) {
digitalWrite(PinSSR5, LOW);
SSR5on = 1;
}
else if (temp5>TargetTemp5+0.5) {
digitalWrite(PinSSR5, HIGH);
SSR5on = 0;
}
if (temp6<TargetTemp6-0.5) {
digitalWrite(PinSSR6, LOW);
SSR6on = 1;
}
else if (temp6>TargetTemp6+0.5){
digitalWrite(PinSSR6, HIGH);
SSR6on = 0;
}
if (temp7<TargetTemp7-0.5) {
digitalWrite(PinSSR7, LOW);
SSR7on = 1;
}
else if (temp7>TargetTemp7+0.5){
digitalWrite(PinSSR7, HIGH);
SSR7on = 0;
}
if (temp8<TargetTemp8-0.5) {
digitalWrite(PinSSR8, LOW);
SSR8on = 1;
}
else if (temp8>TargetTemp8+0.5){
digitalWrite(PinSSR8, HIGH);
SSR8on = 0;
}
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();
}
else if (strncmp( "?ttemp1=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp1") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp1 = value;
EEPROM.write(0, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp2=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp2") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp2 = value;
EEPROM.write(2, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp3=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp3") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp3 = value;
EEPROM.write(4, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp4=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp4") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp4 = value;
EEPROM.write(6, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp5=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp5") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp5 = value;
EEPROM.write(14, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp6=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp6") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp6 = value;
EEPROM.write(16, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp7=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp7") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp7 = value;
EEPROM.write(18, value);
}
}
bfill.emit_p(http_Found);
}
else if (strncmp( "?ttemp8=" , data , 8 ) == 0)
{
if (ether.findKeyVal(data + 1, TargetTemperarureTextbox , sizeof TargetTemperarureTextbox , "ttemp8") > 0)
{
byte value = atoi(TargetTemperarureTextbox); // command to convert a string to number
if ((value >=0) && (value <=100)) //if the temperature entered is within the range of 0-100
{
TargetTemp8 = value;
EEPROM.write(20, value);
}
}
bfill.emit_p(http_Found);
}
}
ether.httpServerReply(bfill.position());
}
}
float tempread(byte sensoraddr[])
// error codes:
// -1 no sensors found
// -2 invalid CRC
// -3 not a DS1820
{
byte i;
byte present = 0;
byte data[12];
byte addr[8];
//int HighByte, LowByte, TReading, SignBit, Tc_100, Tf_100, Whole, Fract;
for ( i = 0; i < 8; i++) {
addr[i]=sensoraddr[i];
}
ds.reset(); // pulse the pins and wait for a response to reset the DS1820
ds.select(addr); // 0x55 (MATCH_ROM) followed by the address of the 1820 to talk to.
// ds.write(0x44,1); // start conversion, with parasite power on at the end
ds.write(0x44,0); //PARASITE POWER OFF
// delay(800);
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
float temp = (float)raw / 16.0;
return temp;
}
... тупо добавил во все значения ещё по 4. Увеличил значение byte Ethernet::buffer до [7000] ... заливается в Мегу
Вы уверены, что Вам ОЗУ хватает? Там в Меге вроде всего 8192 байта, а Вы буфер на 7000 завели. Точно хватает? Убедитесь для начала в этом, а там уж смотреть будем.
Памяти точно хватает. При нехватке памяти скетч не зальется. а тут заливается. но как я уже говорил, 7000 могу изменить на 5000. результат будет такой-же.
Да, нет, это при нехватке flash памяти не зальётся, а при нехватке ОЗУ зальётся ещё как. 5000 тоже много. А сколько,кстати, Вам реально нужно? Вы считали?
Всё-таки, поставьте необходимые печати в Serial и твёрдо убедитесь, что с памятью всё в порядке.
Сколько нужно я не считал, по той простой причине, что не умею. я ставил разные значения начиная от 1420 (как в оригинальном скетче) до 7500, при котором памяти уже не хватало.
Поставить "необходимые печати" в сериал не могу по той-же причине - не умею.
я сейчас изменил значение на 3000. вот что написано при компиляции: Sketch uses 18 558 bytes (7%) of program storage space. Maximum is 253 952 bytes.
Если подскажете, как посчитать и поставить печати - я сделаю.
Ну, почситать-то несложно. Для чего этот буфер используется? Вы пихаете туда свой HTML код. Вот и посчитайте сколько он занимает места.
Что касается свободной памяти, то вот здесь есть библиотека, которая содержит функции способные рассказать ВСЁ о том как у Вас используется память, сколько занято. сколько свободно, сколько недоступно. Там есть и коды и примеры и пояснения - http://andybrown.me.uk/2011/01/01/debugging-avr-dynamic-memory-allocation/
Спасибо. Теперь у меня есть два неработающих скетча.
Методом построчного увеличения кода пришел к мысли, что видимо, действительно не хватает памяти. Хотя это очень для меня странно. Первоначальный скетч писался под Uno, где ОЗУ в 4 раза меньше. Но так как я не программист ниразу, для меня работа с памятью - темный лес и куча дров. Дабы не плодить тем, спрошу тут: а существует способ "перехода" с ENC28J60 на Wiznet W5100? Суть перехода: закинуть на SD карту файл со страницей и кидать туда показания датчиков. Вообще, такое возможно?
В общем, если кому интересно - проблема была в ограничении ENC28J60. Мне не удалось найти это ограничение в библиотеке, возможно плохо или не там искал, но если количество всех символов HTML кода превышает 1279, страница не будет загружаться. Урезав и оптимизировав всё, что можно, мне удалось сделать рабочим скетч на 8 термодатчиков. Если кому сей скетч интересен - скажите, выложу.
Мысль переделать скетч на использование W5100 не оставила меня, но вроде как есть проблема "зависания" W5100 через 15-20 минут активной работы. Сам с этим не сталкивался, утверждать не буду. Через пару-тройку недель должен мне "приехать" W5500, попробую сразу на него перескочить. Если у кого есть опыт перехода с ENC на W5100 или, что лучше, на W5500 - поделитесь опытом, плз.
Методом построчного увеличения кода пришел к мысли, что видимо, действительно не хватает памяти. Хотя это очень для меня странно. Первоначальный скетч писался под Uno, где ОЗУ в 4 раза меньше. Но так как я не программист ниразу, для меня работа с памятью - темный лес и куча дров. Дабы не плодить тем, спрошу тут: а существует способ "перехода" с ENC28J60 на Wiznet W5100? Суть перехода: закинуть на SD карту файл со страницей и кидать туда показания датчиков. Вообще, такое возможно?
Вот я в соседней теме вопрос про карту задал. Пока молчание. Тоже не хватает места в основной программе для записи на карту. Поэтому скидываю поэлементно на другую NANO, которая с картой. Все работает, место практически не занимает. Но нормально активируется только resetом.
Я отказался от идеи хранить на карте памяти. Мне бы переделать скетч под W5100.