ENC28J60 проблемы с GET

mitekg
Offline
Зарегистрирован: 14.05.2013

Уперся в непонятную мне проблему:

есть eth модуль на ENC28J60

есть мега к которой еще подключен nrf24 с библиотекой от маньяка

делаю след.

1. добавил пример с web-server в общий код. работает.

2. добавил раздел с вызовом через GET узла, вот тут и возникает проблема

за основу взял https://github.com/jcw/ethercard/blob/master/examples/webClient/webClien...

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

Спасибо.

/*
 Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Example of a sensor network 
 *
 * This sketch demonstrates how to use the RF24Network library to
 * manage a set of low-power sensor nodes which mostly sleep but
 * awake regularly to send readings to the base.
 *
 * The example uses TWO sensors, a 'temperature' sensor and a 'voltage'
 * sensor.
 *
 * To see the underlying frames being relayed, compile RF24Network with
 * #define SERIAL_DEBUG.
 *
 * The logical node address of each node is set in EEPROM.  The nodeconfig
 * module handles this by listening for a digit (0-9) on the serial port,
 * and writing that number to EEPROM.
 */

#include <avr/pgmspace.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <Tictocs.h>
#include <Button.h>
#include <TictocTimer.h>
#include "nodeconfig.h"
#include "sleep.h"
#include "S_message.h"
#include "printf.h"
#include <EtherCard.h>

//-----eth
#define STATIC 0  // set to 1 to disable DHCP (adjust myip/gwip values below)

#if STATIC
// ethernet interface ip address
static byte myip[] = { 192,168,1,200 };
// gateway ip address
static byte gwip[] = { 192,168,1,1 };
#endif
// ethernet mac address - must be unique on your network
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer[700]; // tcp/ip send and receive buffer

//-----eth
static BufferFiller bfill;  // used as cursor while filling the buffer
struct port_param_t{String name; String value;};
#define MAX_PARAMS 20 // сколько параметров максимально мы умеем парсить
port_param_t params[MAX_PARAMS]; // в этот массив будем сохранять наши парсенные параметры
byte parsedParams=0; // сколько параметров нам удалось напарсить




// This is for git version tracking.  Safe to ignore
#ifdef VERSION_H
#include "version.h"
#else
const char program_version[] = "Unknown";
#endif

// Pin definitions
#ifndef PINS_DEFINED
#define __PLATFORM__ "Getting Started board"

// Pins for Eth + Nrf21
const int SS_nrf21 = 14;
const int SS_eth = 1;


// Pins for radio
const int rf_ce = 8;
const int rf_csn = 7;

// Pins for sensors
const int temp_pin = A2;
const int voltage_pin = A3;

// Pins for status LED, or '0' for no LED connected
const int led_red = 22; 
const int led_yellow = 23; 
const int led_green = 25; 

// Button to cont=rol modes
const int button_a = 4;

// What voltage is a reading of 1023?
const unsigned voltage_reference = 5 * 256; // 5.0V
#endif

RF24 radio(rf_ce,rf_csn);
RF24Network network(radio);

// Our node configuration 
eeprom_info_t this_node;

// How many measurements to take.  64*1024 = 65536, so 64 is the max we can fit in a uint16_t.
const int num_measurements = 64;

// Sleep constants.  In this example, the watchdog timer wakes up
// every 4s, and every single wakeup we power up the radio and send
// a reading.  In real use, these numbers which be much higher.
// Try wdt_8s and 7 cycles for one reading per minute.> 1
const wdt_prescalar_e wdt_prescalar = wdt_4s;
const int sleep_cycles_per_transmission = 1;

// Non-sleeping nodes need a timer to regulate their sending interval
Timer send_timer(2000);

// Button controls functionality of the unit
Button ButtonA(button_a);

// Long-press button
Button ButtonLong(button_a,1000);

/**
 * Convenience class for handling LEDs.  Handles the case where the
 * LED may not be populated on the board, so always checks whether
 * the pin is valid before setting a value.
 */

class LED
{
private:
  int pin;
public:
  LED(int _pin): pin(_pin)
  {
    if (pin > 0)
    {
      pinMode(pin,OUTPUT);
      digitalWrite(pin,LOW);
    }
  }
  void write(bool state) const
  {
    if (pin > 0)
      digitalWrite(pin,state?HIGH:LOW);
  }
  void operator=(bool state)
  {
    write(state);
  }

};

/**
 * Startup LED sequence.  Lights up the LEDs in sequence first, then dims 
 * them in the same sequence.
 */

class StartupLEDs: public Timer
{
private:
  const LED** leds;
  const LED** current;
  const LED** end;
  bool state;
protected:
  virtual void onFired(void)
  {
    (*current)->write(state);
    ++current;
    if ( current >= end )
    {
      if ( state )
      {
	state = false;
	current = leds;
      }
      else
	disable();
    }
  }
public:
  StartupLEDs(const LED** _leds, int _num): Timer(250), leds(_leds), current(_leds), end(_leds+_num), state(true)
  {
  }
};

/**
 * Calibration LED sequence.  Flashes all 3 in unison
 */
class CalibrationLEDs: public Timer
{
  const LED** leds;
  const LED** end;
  bool state;
protected:
  void write()
  {
    const LED** current = end;
    while (current-- > leds)
      (*current)->write(state);
  }
  virtual void onFired() 
  {
    state = ! state;
    write();
  }
public:
  CalibrationLEDs(const LED** _leds, int _num, unsigned long duration = 500): Timer(duration), leds(_leds), end(_leds+_num), state(false)
  {
    Timer::disable();
  }
  void begin()
  {
    Updatable::begin();
  }
  void reset()
  {
    state = true;
    write();
    Timer::reset();
  }
  void disable()
  {
    state = false;
    write();
    Timer::disable();
  }
};

LED Red(led_red), Yellow(led_yellow), Green(led_green);

const LED* leds[] = { &Red, &Yellow, &Green }; 
const int num_leds = sizeof(leds)/sizeof(leds[0]);
StartupLEDs startup_leds(leds,num_leds);
CalibrationLEDs calibration_leds(leds,num_leds);

// Nodes in test mode do not sleep, but instead constantly try to send
bool test_mode = false;

// Nodes in calibration mode are looking for temperature calibration
bool calibration_mode = false;


void setup(void)
{
  //
  // Print preamble
  //
  
  Serial.begin(57600);
  
  
  // --eth--
  Serial.println("\n[backSoon]");
  
  if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0) 
    Serial.println( "Failed to access Ethernet controller");
  #if STATIC
  ether.staticSetup(myip, gwip);
  #else
  if (!ether.dhcpSetup())
    Serial.println("DHCP failed");
  #endif
  
  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip);  
  ether.printIp("DNS: ", ether.dnsip);  
  // --eth--
  
  printf_begin();
  printf_P(PSTR("\n\rRF24Network/examples/sensornet/\n\r"));
  printf_P(PSTR("PLATFORM: " __PLATFORM__ "\n\r"),program_version);
  printf_P(PSTR("VERSION: %s\n\r"),program_version);
  
  //
  // Pull node address out of eeprom 
  //

  // Which node are we?
  this_node = nodeconfig_read();

  //
  // Prepare sleep parameters
  //

  // Only the leaves sleep.  Nodes 01-05 are presumed to be relay nodes. 
  if ( ! this_node.relay )
    Sleep.begin(wdt_prescalar,sleep_cycles_per_transmission);

  //
  // Set up board hardware
  //
  ButtonA.begin();
  ButtonLong.begin();

  // Sensors use the stable internal 1.1V voltage
#ifdef INTERNAL1V1
  analogReference(INTERNAL1V1);
#else
  analogReference(INTERNAL);
#endif

  // Prepare the startup sequence
  send_timer.begin();
  startup_leds.begin();
  calibration_leds.begin();

  //
  // Bring up the RF network
  //

  SPI.begin();
  radio.begin();
  network.begin(/*channel*/ 92, /*node address*/ this_node.address);

}

bool Param2Msg(void* port_param_t, void* S_message)
{

	return true;
}

void NRF21(void)
{
  // Update objects
  theUpdater.update();

  // Pump the network regularly
  network.update();

  // If we are the base, is there anything ready for us?
  while ( network.available() )
  {
    // If so, grab it and print it out
    RF24NetworkHeader header;
    S_message message;
    network.read(header,&message,sizeof(message));
    printf_P(PSTR("%lu: APP Received #%u %s from 0%o\n\r"),millis(),header.id,message.toString(),header.from_node);
    
  }

  // If we are the kind of node that sends readings, AND it's time to send
  // a reading AND we're in the mode where we send readings...
  if ( this_node.address > 0 && ( ( Sleep && ! test_mode ) || send_timer.wasFired() ) && ! calibration_mode && ! startup_leds )
  {
    // Transmission beginning, TX LED ON
    Yellow = true;
    if ( test_mode )
    {
      Green = false;
      Red = false;
    }

    int i;
    S_message message;
    // Take the temp reading 
    i = num_measurements;
    uint32_t reading = 0;
    while(i--)
      reading += analogRead(temp_pin);

    // Convert the reading to celcius*256
    // This is the formula for MCP9700.
    // C = reading * 1.1
    // C = ( V - 1/2 ) * 100
    message.temp_reading = ( ( ( reading * 0x120 ) - 0x800000 ) * 0x64 ) >> 16;

    // Take the voltage reading 
    i = num_measurements;
    reading = 0;
    while(i--)
      reading += analogRead(voltage_pin);

    // Convert the voltage reading to volts*256
    message.voltage_reading = ( reading * voltage_reference ) >> 16; 

    printf_P(PSTR("---------------------------------\n\r"));
    printf_P(PSTR("%lu: APP Sending %s to 0%o...\n\r"),millis(),message.toString(),0);
    
    // Send it to the base
    RF24NetworkHeader header(/*to node*/ 0, /*type*/ test_mode ? 's' : 'S');
    bool ok = network.write(header,&message,sizeof(message));
    if (ok)
    {
      if ( test_mode )
	  Green = true;
      printf_P(PSTR("%lu: APP Send ok\n\r"),millis());
    }
    else
    {
      if ( test_mode )
	  Red = true;
      printf_P(PSTR("%lu: APP Send failed\n\r"),millis());
    }

    // Transmission complete, TX LED OFF
    Yellow = false;
   
    if ( Sleep && ! test_mode ) 
    {
      // Power down the radio.  Note that the radio will get powered back up
      // on the next write() call.
      radio.powerDown();

      // Be sure to flush the serial first before sleeping, so everything
      // gets printed properly
      Serial.flush();
      
      // Sleep the MCU.  The watchdog timer will awaken in a short while, and
      // continue execution here.
      Sleep.go();
    }
  }

  // Button
  unsigned a = ButtonA.wasReleased();
  if ( a && a < 500 )
  {
    // Pressing the button during startup sequences engages test mode.
    // Pressing it after turns off test mode.
    if ( startup_leds )
      test_mode = true;
    else if ( test_mode )
    {
      test_mode = false;
      Green = false;
      Red = false;
    }
    else if ( calibration_mode )
    {
      calibration_mode = false;
      test_mode = true;
      calibration_leds.disable();
    }
  }

  // Long press
  if ( ButtonLong.wasPressed() && test_mode )
  {
    test_mode = false;
    calibration_mode = true;
    calibration_leds.reset();
  }

  // Listen for a new node address
  nodeconfig_listen();
}

int strtoint(String str) // Процедура переобразования строки в число
{
  int tempInt;
  char rez[str.length()+1];
  str.toCharArray(rez, sizeof(rez));
  tempInt = atoi(rez);
  return tempInt;
}

void parseParams(char* inputString)
{ 
 parsedParams=0; // пока ничего не напарсили
 char* buffer=strtok(inputString,"?"); // лучше так проверять/пропускать вопросилово
 
 if(buffer!=NULL)
 {
   for(buffer=strtok(NULL,"&"); buffer!=NULL;     buffer=strtok(NULL,"&") ) 
   {
    String buffer1= String(buffer);
    params[parsedParams].name= buffer1.substring(0,buffer1.indexOf('='));   //достаем имя
    params[parsedParams].value=buffer1.substring(buffer1.indexOf('=')+1); //достаем значение в integer
    parsedParams++; // отмечаем сколько удалось распарсить
   }
   if(parsedParams>MAX_PARAMS-1)return; // больше нет места куда сохранять парсенное.
  }  
  
}



void printParams(){
  Serial.println(parsedParams);
  for(byte i=0;i<parsedParams;i++){
      // TODO: всю эту кучу принтов можно заменить одним sprintf
      Serial.print(params[i].name);
      Serial.print(" -> ");
      Serial.println(params[i].value);
    //  Serial.print("=");
    //  Serial.println(params[i].value,DEC);
  }
}

static uint32_t timer;
char website[] PROGMEM = "www.google.com";
static void my_callback (byte status, word off, word len) {
  Serial.println(">>>");
  Ethernet::buffer[off+300] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
}


void EthGet(void)
{
	ether.packetLoop(ether.packetReceive());
	if (millis() > timer) 
	{
		timer = millis() + 5000;
		Serial.println();
		Serial.print("<<< REQ ");
		ether.browseUrl(PSTR("/foo/"), "bar", website, my_callback);
	}
}

void Eth(void)
{   
  word pos = ether.packetLoop(ether.packetReceive());  // получаем запрос или ответ
  if (pos) 
  {
    bfill = ether.tcpOffset();
    char *data = (char *) Ethernet::buffer + pos;
    parseParams(data);
	// формируем ответ с переменными
    bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
    "Content-Type: text/html\r\n"
    "Pragma: no-cache\r\n"
    "\r\n"
    "<meta http-equiv='refresh' content='5'/>"
    "<title>RBBB server</title>" 
    "<h1>1 - $S<br></h1>"),
    "123");
    ether.httpServerReply(bfill.position());
  }  
    // wait for an incoming TCP packet, but ignore its contents
  /*if (ether.packetLoop(ether.packetReceive())) 
  {
    bfill = ether.tcpOffset();
    bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
    "Content-Type: text/html\r\n"
    "Pragma: no-cache\r\n"
    "\r\n"
    "<meta http-equiv='refresh' content='1'/>"
    "<title>RBBB server</title>" 
    "<h1>$D$D:$D$D:$D$D</h1>"),
     10, 20, 30, 40, 50, 60);
     ether.httpServerReply(bfill.position());
    
  }*/
}

void loop(void)
{
  digitalWrite(SS_eth, HIGH);
  digitalWrite(SS_nrf21, LOW);
  NRF21();
  
  digitalWrite(SS_eth, LOW);
  digitalWrite(SS_nrf21, HIGH);
  EthGet();
  Eth();
  
  
  
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

 

toc
Offline
Зарегистрирован: 09.02.2013

Возможно, не хватает оперативной памяти. Какой МК?

toc
Offline
Зарегистрирован: 09.02.2013

Объявленная в 495 строке переменная не  инициализирована. Не знаю плохо ли это, но я бы присвоил 0. 

Задержка в 508 строке чтобы гугл не задосить?

 

toc
Offline
Зарегистрирован: 09.02.2013

Попробуйте собрать работающий пример с ограниченным функционалом. Только веб сервер и веб клиент, без RF24.

mitekg
Offline
Зарегистрирован: 14.05.2013

дело не в nrf (пробовал отключать).

Памяти с запасом, там мега2560

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