ENC28J60 проблемы с GET
- Войдите на сайт для отправки комментариев
Чт, 15/08/2013 - 09:56
Уперся в непонятную мне проблему:
есть 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
Возможно, не хватает оперативной памяти. Какой МК?
Объявленная в 495 строке переменная не инициализирована. Не знаю плохо ли это, но я бы присвоил 0.
Задержка в 508 строке чтобы гугл не задосить?
Попробуйте собрать работающий пример с ограниченным функционалом. Только веб сервер и веб клиент, без RF24.
дело не в nrf (пробовал отключать).
Памяти с запасом, там мега2560
задержка чтоб как раз успеть получить ответ после запроса. Оно асинхронно работает.