Go Down

Topic: ENC28J60 Ethernet beste Library (Read 29156 times) previous topic - next topic

kohleick

danke,

das Modul entspricht dem oben im thread. Ich habe einmal in der Ethercard library nachgeschaut: dort ist das CS auf pin 8, in Deinen auf 10, alle anderen 3 pins entsprechen denen in Deinen h Files (11,12,13). Ich habe den pin geändert und die Beispiele klappen nach wie vor nicht. Gibt es sonst noch einen hardware abhängigen Teil verändert wurde ?


s


ntruchsess

nein, hardwaremäßig gibt's sonst nichts, der Chip hängt ja nur an diesen SPI-pins. Ich habe selber so ein Modul (ich weiß nicht, ob es wirklch das gleiche ist, aber es sieht jedenfalls genauso aus, wie das, was mir Google dazu ausgespuckt hat) zum Testen benutzt und bei mir funktionierts.

Man kann verschiedene Debug-level in der UIPEthernet.h anstellen und dann auf der seriellen Schnittstelle schauen, ob die Kommunikation mit dem Modul denn überhaupt was tut.

- Norbert

kohleick

Hallo,

danke für die Hinweise.

Ich hatte das Modul auf ein selbstgestricktes Shield mit der Pinbelegung der Ethercard gesteckt, d.h. CS=8, ansonsten 11,12,13 wie auch in der UIPlib. Wie schon gesagt klappte es nicht, in Enc28j60Network.h den CS auf Pin 8 zu setzen, um die Library zu nutzen. Ich habe dann den Pin 8 auf Pin 10 gelegt (verbunden), um die in der Library per Standard vorgegebene Pinkonfiguration zu nutzen - und die Originalversion der Library genutzt. Es klappte anstandslos.

Mir scheint, dass irgendwo in der Library der zusätzlich noch Pin 10 postuliert wird. Eine Änderung von CS 10 auf 8 in Enc28j60Network.h hat keinen (bzw. nur begrenzten) Effekt.

Gruss

s

ntruchsess

danke für den Hinweis, dann werde ich das mal mit anderen Pins durchtesten... das kriege ich schon raus, wenn da in Bezug auf CS noch irgendwo der Wurm drin ist.

- Norbert

johnny1

Hi,

habe auch versucht die Library für mein Projekt zu verwenden.
Die einzelnen Demo-Programme funktionieren soweit problemlos - klasse Arbeit, erleichtert
die Verwendung des ENC28J60 mit dem Arduino doch sehr. Danke!

Wenn ich alllerdings mein fertiges Programm mit der Library erweitern will bekomme ich
den seltsammen Effekt, dass der Controller ständig einen Reset ausführt.

Mein Programm selbst steuert ein LCD-Display mit Touchfunktion an (MI0283QT)
Das Display ist über I2C angebunden. Es funktioniert alleine problemlos.
Ich wollte nun das Programm um Ethernet-Funktionen
erweitern. Über SPI (MISO, MOSI, CLK, CS) ist ein Ethernet-Modul mit dem ENC28J60-Chip
angeschlossen. Beide Hardwareteile alleine funktionieren (Display oder Ethernet).

Wenn ich allerdings versuche das Display über I2C und Ethernet über SPI anzusprechen
führt der Controller innerhalb der Setup-Routine einen Reset durch.

Ich hab den Fehler eingegrenzt und konnte feststellen, dass die Probleme dann auftreten wenn
ich den client definiere also:

Code: [Select]
EthernetClient client;

Vielleicht sollte ich noch sagen, dass ich aus Mangel an Speicher UDP deaktiviert habe, so wie
Norbert es hier beschrieben hat (in der uip-conf.h das define für UIP_CONF_UDP auf 0  setzen).

Sind Probleme bekannt, bei gleichzeitiger Nutzung von SPI und I2C ?

Was macht eigentlich
Code: [Select]
EthernetClient client; so großartiges, dass
danach mein Code nicht mehr läuft?

Hier vielleicht noch zur Info die setup-Routine:
(Der komplette Code ist sehr viel Holz - wenn es jemand interessiert gerne mehr)


Code: [Select]
void setup(){

  uint16_t x=0, y=0;
 
  Serial.begin(9600);
 
  //init Wire lib
  Wire.begin();
  delay(100);
  //get firmware version
  Serial.print("version: ");
  send_i2c(CMD_VERSION);
  Wire.requestFrom(I2C_ADDR, 4); //request 4 bytes
  if (Wire.available())
    Serial.println("Wire available!");
  else
  {
    Serial.println("Wire not available!"); 
    send_i2c(CMD_VERSION);
    Wire.requestFrom(I2C_ADDR, 4); //request 4 bytes
  }
  while(Wire.available())
  {
//    Serial.println("Wire available!");
    char c = Wire.read();
    if (c == 0)
    {
        Serial.print(".");     
        Wire.begin();
        delay(100);
        send_i2c(CMD_VERSION);
        Wire.requestFrom(I2C_ADDR, 4); //request 4 bytes
       
    }
    Serial.print(c);
  }
  Serial.println("");

  //get features
  Serial.print("features: ");
  send_i2c(CMD_FEATURES);
  Wire.requestFrom(I2C_ADDR, 1); //request 1 bytes
  while(Wire.available())
  {
    char c = Wire.read();
    if(c & FEATURE_LCD){ Serial.print("LCD "); }
    if(c & FEATURE_TP) { Serial.print("TP ");  }
    if(c & FEATURE_ENC){ Serial.print("ENC "); }
    if(c & FEATURE_NAV){ Serial.print("NAV "); }
    if(c & FEATURE_LDR){ Serial.print("LDR "); }
  }
  Serial.println("");

  //get width and height
  Serial.print("width/height: ");
  send_i2c(CMD_LCD_WIDTH);
  Wire.requestFrom(I2C_ADDR, 2); //request 2 bytes
  if(Wire.available())
  {
    x  = Wire.read()<<8;
    x |= Wire.read()<<0;
  }
  Serial.print(x, DEC);
  Serial.print("/");
  send_i2c(CMD_LCD_HEIGHT);
  Wire.requestFrom(I2C_ADDR, 2); //request 2 bytes
  if(Wire.available())
  {
    y  = Wire.read()<<8;
    y |= Wire.read()<<0;
  }
  Serial.print(y, DEC);
  Serial.println("");

  //backlight
  Serial.println("backlight...");
  Wire.beginTransmission(I2C_ADDR);
  Wire.write(CMD_LCD_LED);
  Wire.write(50); //0...100
  Wire.endTransmission(true);

  //clear screen
  Serial.println("clear...");
  Wire.beginTransmission(I2C_ADDR);
  Wire.write(CMD_LCD_CLEARBG);
  Wire.endTransmission(true);

  Serial.println("...end");

  radio();  // Maske auf LCD zeichnen
   
 
  //enable touchpanel
  Wire.beginTransmission(I2C_ADDR);
  Wire.write(CMD_CTRL);
  Wire.write(CMD_CTRL_FEATURES);
  Wire.write(FEATURE_TP);
  Wire.endTransmission();

  // init ethernet

  Ethernet.begin(mymac, myip);

}



Wenn ich das Programm kompiliere und zum ATMEGA 328 sende bekomme ich im seriellen log:


0.04
LCD TP LDR
width/height: 320/240
backlight...
clear...
...end


0.04
LCD TP LDR
width/height: 320/240
backlight...
clear...
...end


0.04
LCD TP LDR
width/height: 320/240
backlight...
clear...
...end

usw. ständig ca. alle 200 ms diese 6 Zeilen, so als ob alle 200ms jemand reset drückt ??!

Hat jemand eine Idee wo ich suchen könnte??


johnny1

Hi nochmal  :)

noch ein Hinweis zu der Deaktivierung von UDP:
Wenn ich in der uip-conf.h das define für UIP_CONF_UDP auf 0
bekomme ich beim Compilieren mehrere redefined-Warnings:

Code: [Select]

...\Arduino\libraries\arduino_uip/utility/uip-conf.h:50:1: warning: "UIP_CONF_UDP" redefined
In file included from ...\Arduino\libraries\arduino_uip/utility/mempool_conf.h:3,
                 from ...\Arduino\libraries\arduino_uip/utility/mempool.h:28,
                 from ...\Arduino\libraries\arduino_uip/UIPUdp.h:26,
                 from ...\Arduino\libraries\arduino_uip/Dhcp.h:7,
                 from ...\Arduino\libraries\arduino_uip/UIPEthernet.h:25,
                 from hzstv10.ino:4:
...\Arduino\libraries\arduino_uip/utility/uipethernet-conf.h:9:1: warning: this is the location of the previous definition
In file included from ...\Arduino\libraries\arduino_uip/Dhcp.h:7,
                 from ...\Arduino\libraries\arduino_uip/UIPEthernet.h:25,
                 from hzstv10.ino:4:


Sollte aber kein Problem sein und hat vermutlich mit meinem Problem nichts zu tun ??!!
...

ntruchsess

ins blaue geraten: das RAM reicht nicht.
probier bitte mal die Version aus dem 'static-memory' branch. Da habe ich alle mallocs aus der Library ausgebaut und alle Strukturen werden schon unmittelbar nach dem reset (per deklaration) initialisiert. Das sollte speichermäßig stabilier sein.

Falls Du nicht 4 parallele Client-verbindung brauchst, kannst Du den RAM-bedarf über die uipethernet-conf.h beeinflussen. UIP_SOCKET_NUMPACKETS definiert die Anzahl der (noch ungelesen) empfangbaren Pakete, UIP_CONF_MAX_CONNECTIONS die Zahl der parallel möglichen Verbindungen.

Das verbleibende freie RAM kannst Du mit einer der hier beschriebenen Methoden ermitteln.

ach so: wg 'EthernetClient client' - das ist zwar nur der Konstruktor, aber damit hängt implizit die halbe UIPEthernet-library dran, weil der Konstruktor (in der released-version) erst den callback für die EthernetClient-funktionalität registriert - wenn Dein Sketch außer einem Ethernet.begin() nichts mit der library macht, dann wird vom Linker auch praktisch nichts davon in das compilierte binary kopiert.

- Norbert

johnny1

Hm, RAM - gute Idee!
Würde auch die Symptome erklären, die ich bei verschiedenen Tests bekommen habe
(Unerklärliche Werte von Variablen, etc.)

Ich suche da mal in dieser Richtung ...

johnny1

Ok, das sieht wirklich nach einem Problem mit zu wenig RAM aus.
Hab mal mit "avr-size" mein Programm untersucht:

Code: [Select]
avr-size --mcu=atmega328 -C hzstv10.cpp.elf
AVR Memory Usage
----------------
Device: atmega328

Program:   27398 bytes (83.6% Full)
(.text + .data + .bootloader)

Data:       2126 bytes (103.8% Full)
(.data + .bss + .noinit)



Mist, über 100% und dann noch ohne HEAP und STACK  =(

Mit dem static memory branch bekomme ich:

Code: [Select]
avr-size --mcu=atmega328 -C hzstv10.cpp.elf
AVR Memory Usage
----------------
Device: atmega328

Program:   26590 bytes (81.1% Full)
(.text + .data + .bootloader)

Data:       2154 bytes (105.2% Full)
(.data + .bss + .noinit)


Noch ein paar Bytes mehr, aber wenn da keine mallocs mehr drin sind brauch ich keinen
freien Speicher für den HEAP.


OK, dann also noch die Anzahl der ungelesenen Pakete und die Anzahl max Connections beschränken:

Code: [Select]
/* for TCP */
/* save RAM:
#define UIP_SOCKET_NUMPACKETS    5
#define UIP_CONF_MAX_CONNECTIONS 4
*/
#define UIP_SOCKET_NUMPACKETS    3
#define UIP_CONF_MAX_CONNECTIONS 2



Was haben wir jetzt?

Code: [Select]
avr-size --mcu=atmega328 -C hzstv10.cpp.elf
AVR Memory Usage
----------------
Device: atmega328

Program:   26562 bytes (81.1% Full)
(.text + .data + .bootloader)

Data:       1920 bytes (93.8% Full)
(.data + .bss + .noinit)


Sieht besser aus  :)
Hab ich noch genug STACK für die Fuktionsaufrufe ??

Hm, man kann doch mit PROGMEM strings im Flash ablegen - das spart auch RAM!
OK, dann muss ich wohl mein Programm noch etwas umbauen ...
Schon mal Danke, Danke, Danke an Norbert!!

Johnny

Serenifly

Für Strings gibt es auch das F-Makro:

Code: [Select]

Serial.println(F("String im Flash"));

ntruchsess


Hab mal mit "avr-size" mein Programm untersucht:
Code: [Select]
Data:       2126 bytes (103.8% Full)
Mit dem static memory branch bekomme ich:
Code: [Select]
Data:       2154 bytes (105.2% Full)

Das ist ja schick, nur 28 Bytes mehr. Ich hätte ja mit einem größeren Zuwachs gerechnet, wobei malloc selbst ja vermutlich auch ganz gut Speicher braucht. 'Static-memory' ist auch noch nicht final, ich werde vermutlich den 'data'-pointer in der UIPClient.cpp durch ein uint8_t ersetzen und noch ein paar kleinigkeiten ändern. Mal sehen, ob das noch was (hinsichtlich codesize und Rambedarf) bringt.
'avr-size' hatte ich gar nicht auf dem Radar... sollte man wirklich routinemäßig hernehmen um codechanges zu bewerten.

- Nobert

johnny1

Hm, ich habe in meinem Programm ein array von Strings definiert:

char senderliste[15][15] = {"Sender1", "Sender2", "Sender 3", ...};

Wenn ich mir die Symbole aus dem elf-File ausgeben lasse (mit avr-nm)
bekomme ich:

Code: [Select]
[
...
00004ff4 00000152 T _ZN9MI0283QT98fillRectEjjjjj
00003b20 00000156 t uip_arp_update
00003cde 0000016c T uip_arp_arpin
0000481e 0000017e T _ZN15Enc28J60Network4initEPh
000049c8 000001ae T _ZN10MemoryPool10allocBlockEj
00004e10 000001e4 T _ZN9MI0283QT98drawCharEjjchjj
00003e4a 00000204 T uip_arp_out
0080019c 00000258 D senderliste
00001e8a 00000288 T _ZN9UIPClient12uip_callbackEv
000010f0 0000030a T _Z5radiov
00005586 00000322 T __vector_24
000018c0 0000033c T setup
00000612 000003ba T vfprintf
00000068 00000480 T font_PGM
000013fa 000004c6 T loop
00002e8a 00000c96 T uip_process



Aus der man-page zu avr-nm:

Code: [Select]

"D"
"d" The symbol is in the initialized data section.


Wo  liegt nun die "initialized data section"?

Bei
             http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc
steht:
Quote
Alle Symbole mit einem "T" (globale Funktionen), "t" (statische Funktionen) und letztlich auch mit einem "D" oder "d" (globale bzw. statische Daten, die haben ihre Initialisierungswerte im ROM) betreffen das FLASH-ROM. "B" und "b" brauchen ausschließlich RAM (werden beim Start mit 0 initialisiert). Die erste Spalte ist die Adresse des Symbols, die zweite ist die Größe (beides hexadezimal)


Ich hätte die "data section" im RAM gesucht?

Bringt mir jetzt die Verwendung des F-Makros noch mehr RAM ??

Johnny



johnny1

Ok, ANtwort selbst gefunden - man muss nur weiter lesen  :~

Der String wird im Flash gespeichert und beim Initialilsieren ins RAM kopiert.

Also versuch ich jetzt einfach alle konstanten Strings im Flash zu lassen ...

Serenifly

Das F-Makro ist für print gedacht, damit man das schnell und kurz schreiben kann.

Wenn du sowas wie String Arrays hast, verwende dafür weiterhin PROGMEM und pgm_read_byte/word zum auslesen:
http://arduino.cc/en/Reference/PROGMEM

ntruchsess

mal ein kurzer Hinweis auf die neuen Releases von UIPEthernet:
https://github.com/ntruchsess/arduino_uip/releases

- das Problem keinen anderen Pin als (Hardware-)SS für ENC28J60_CONTROL_CS definieren zu können ist gelöst.
- es wird kein RAM mehr dynamisch, sondern alles beim Start (per declaration) allociert.
- die Arduino 1.5.5 IDE wird unterstützt.
- Flash-bedarf ist ein paar hundert bytes kleiner geworden.

Viel Spaß damit,

Norbert

Go Up