gate nrf24l01+enc28j60

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Добрый день.

Делаю шлюз на данных модулях. Возникли проблемы. Устройство работает через раз, не выполняется php скрипт на сервере. Контроллер собран на Atmega328 c бутлоадером optiboot. Питание на всех мродулях 3.3в 3А, на разьёмах модулей стоят электролиты. Устройство пингутся, отвечает на запрос ?help (значит enc в работе), при поступлении данных по радиоканалу в Serial выводятся соответствующие данные (значит nrf тоже в работе), а скрипт не выполняется :( Если отключить питание, а затем его включить то всё может работать, а может и нет. Незнаю куда копать :(

Вот код





#include "EtherCard.h"
#include <string.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
//-----------------------------------------------------------------------------------
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] =  { 192,168,1,99 };  // adress of gate
static byte gwip[] =  { 192,168,1,20 };
static byte hisip[] = { 192,168,1,163 }; // adress server
byte Ethernet::buffer[700];
static BufferFiller bfill;

const char PROGMEM webserver[]    = "192.168.1.163";
RF24 radio(9,8);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

typedef struct{
  int   NUM;
  int   VCC;
  float TEMP;
  float OTHER;
}
B_t;
B_t data;
//---------------------ответ серверу--------------------------------------
void send_http_ok()
{
  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"));
  ether.httpServerReply(bfill.position());  
}
//--------------------смотрим ответ от appache --------------------------------------- 
static void my_callback (byte status, word off, word len) {// всё можно закоментировать
  Ethernet::buffer[off+300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
}
//----------------------------------------------------------- 
void setup () {
  Serial.begin(9600);
  Serial.println("Start");
  
  ether.begin(sizeof Ethernet::buffer, mymac,7 );
  ether.staticSetup(myip, gwip);
  ether.copyIp(ether.hisip, hisip);
  
  radio.begin();
  radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(1,pipes[0]);
  radio.startListening();
}
//-----------------------------------------------------------
void ethernet()
{
  word pos = ether.packetLoop(ether.packetReceive());
  if(pos)
   { 
    parse_str(pos); // parsing comand
    send_http_ok(); // отсылаем стандартный http request !!обязательно
   }  
}
//-----------------------------------------------------------
void radioch()
{
  if ( radio.available() ) // если пришли данные по радио
  {
      radio.read( &data, sizeof(data) );
      char buffer[250];
      char conv_buffer[11];
      buffer[0] = 0;
      strcat_P(buffer, PSTR("n1="));
      strcat(buffer, itoa(data.NUM, conv_buffer, 10));
      strcat_P(buffer, PSTR("&n2="));    
      strcat(buffer, dtostrf(data.VCC, 2, 0, conv_buffer));    
      strcat_P(buffer, PSTR("&n3="));    
      strcat(buffer, dtostrf(data.TEMP, 2, 2, conv_buffer));    
      strcat_P(buffer, PSTR("&n4="));    
      strcat(buffer, dtostrf(data.OTHER, 2, 2, conv_buffer));
      Serial.println(buffer);
      ether.browseUrl(PSTR("/gate.php?"), buffer, webserver, my_callback);
      delay(10);    
 }  
}
//-----------------------------------------------------------
void loop ()
{
  ethernet();  
  radioch();
}
//---------------------обработки web запросов---------------------------------------
void parse_str(char pos)
{
 if(strstr((char *)Ethernet::buffer + pos, "GET /?help") != 0)
  {
   help();
  }
 if(strstr((char *)Ethernet::buffer + pos, "GET /?status") != 0)
  {
   send_status();
  }
}
//-----------------------------------------------------------------------------------
void send_status()
{
  Serial.print("status...");
  bfill = ether.tcpOffset(); 
//  bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"    // $S - значение float  $D - значение int
//                   "name=street<BR>vcc=$D<BR>temp=$S<P>name=room<BR>vcc=$D<BR>temp=$S"),                                
//                   obj[1].vcc, dtostrf(obj[1].temp,3,2,tempS), obj[2].vcc, dtostrf(obj[2].temp,3,2,tempS));
  ether.httpServerReply(bfill.position());   
}
//-----------------------------------------------------------------------------------
void help()
{
  Serial.print("Help...");
  bfill = ether.tcpOffset(); 
  bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n""<p>Last command</p>"));
  ether.httpServerReply(bfill.position());   
}

Заметил одну особенность, на работу скрипта влияет пауза в 81 строке и размер буфера в 68 строке.

Что может быть?

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Неужели никто не знает?

axill
Offline
Зарегистрирован: 05.09.2011

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

проделайте оптимизацию с тем чтобы сократить как размер скетча так и размер используемов памяти, причем важны именно пики использования как например в функции radioch. Кстати вы там собираете большую строку, ее можно собрать одним вызовом функции sprintf_P, без использования массива для промежуточной конвертации на 11 байт. Но надо посмотреть сократит или увеличит это размер скетча, функция sprintf прожерлива, но остальные функции конвертации тоже прожерливы, вопрос кто кого

axill
Offline
Зарегистрирован: 05.09.2011

И еще. Можете сделать отключаемым использование Serial, или временно закоментировать или используя условную компиляцию (#define #if). И посмотрите что будет. Отключение Serisl высвободит довольно приличный кусок флэша и рама

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

axill, спасибо за совет. при использовании sprintf вообще отказывалось работать, serial убирал но ничего не изменилось. так и не установил от чего зависит работа девайса в целом

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

можно проверить сколько памяти осталось например этим

https://github.com/maniacbug/MemoryFree

или так

http://microsin.net/programming/AVR/arduino-determining-amount-free-and-...

axill
Offline
Зарегистрирован: 05.09.2011

при использовании sprintf строка запроса верно формировалась? sprintf не самая простая в применении функция, много ньюансов

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013




    sprintf(queryString, "n1=%d&n2=%d&n3=%0d.%d&n4=%0d.%d" "\r\n", num, vcc, (int)data.TEMP, abs(d1), (int)data.OTHER, abs(d2));
    ether.browseUrl(PSTR("/gate.php?"), queryString, webserver, my_callback);

результат формирования проверял через





    Serial.println(queryString); 

но это ничего не дало :(

 

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

freeMemory()=763

Вроде норм

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

только вставь в разных местах лупа. может на каком то куске кода память заканчивается

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

все норм, стоит как вкопаный (783)

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

И опять все перестало работать :(

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Перепробовал всё, менял паузы и размер буферов, всё так же. Может железо глючит?

maloicds
maloicds аватар
Offline
Зарегистрирован: 21.03.2013

Собрал железо на макетке, залил скетч, опять через раз работает. С меня пиво тому, кто поможет!!