Difference between revisions of "Arduino notes"

From Noah.org
Jump to navigationJump to search
m
m
Line 47: Line 47:
 
   return rc;
 
   return rc;
 
  }
 
  }
 +
</pre>
 +
 +
== Arduino Ethernet MAC/IP Address tester ==
 +
 +
<pre>
 +
/*
 +
  MAC and IP address hog
 +
 
 +
  This sketch repeatedly requests MAC addresses from DHCP.
 +
  A new MAC address is given for each request.
 +
  Circuit:
 +
  * Ethernet shield attached to pins 10, 11, 12, 13
 +
 +
  created 2012-07-25
 +
  by Noah Spurrier
 +
*/
 +
 +
#include <SPI.h>
 +
#include <Ethernet.h>
 +
#include <IPAddress.h>
 +
 +
// MAC address template.
 +
// Note that this is a "locally administered MAC address".
 +
// Note that the following is true: "0x4e|0x02 == 0x4e"
 +
byte mac[] = { 0x4e, 0x4f, 0x41, 0x48, 0x0, 0x0 };
 +
IPAddress local_ip;
 +
 +
void setup() {
 +
  // Open serial port.
 +
  Serial.begin(9600);
 +
  // Wait for serial port to connect. Needed for Leonardo only.
 +
  while (!Serial) ;
 +
 +
  delay (1000);
 +
  Serial.println();
 +
  Serial.println("Begin hogging MAC:IP address leases on DHCP.");
 +
  for (mac[4] = 0; mac[4] <= 254; mac[4]++){
 +
    for (mac[5] = 0; mac[5] <= 254; mac[5]++){
 +
      Serial.print("MAC: ");
 +
      for (byte thisByte = 0; thisByte < 6; thisByte++) {
 +
        // print the value of each byte of the MAC address:
 +
        Serial.print(mac[thisByte], HEX);
 +
        if (thisByte < 5) Serial.print(":");
 +
      }
 +
      Serial.print(", ");
 +
      Serial.print("IP: ");
 +
      // Start new Ethernet connection. See http://arduino.cc/it/Reference/Ethernet
 +
      // Don't forget to patch Ethernet.cpp to get rid of a memory leak.
 +
      // Without this patch, this sketch will only run for 10 or 15 loops.
 +
      if (Ethernet.begin(mac) == 0) {
 +
        Serial.print("ERROR: Failed to get IP address from DHCP.");
 +
        delay(1000);
 +
      }
 +
      else {
 +
        local_ip = Ethernet.localIP();
 +
        for (byte thisByte = 0; thisByte < 4; thisByte++) {
 +
          // print the value of each byte of the IP address:
 +
          Serial.print(local_ip[thisByte], DEC);
 +
          if (thisByte < 3) Serial.print(".");
 +
        }
 +
      }
 +
      Serial.println();
 +
    }
 +
  }
 +
}
 +
 +
void loop() {
 +
 +
}
 
</pre>
 
</pre>

Revision as of 19:50, 30 July 2012


debug memory problems (out of RAM)

See Arduino Forum on memory usage. This function will return the amount of RAM free. This accounts for the stack and heap used.

int freeRam () {
  // __brkval is the address of the top of the heap if memory has been allocated.
  // If __brkval is zero then it means malloc has not used any memory yet, so
  // we look at the address of __heap_start.
  extern int __heap_start
  extern int *__brkval; // address of the top of heap
  int stack_top; 
  return (int)&stack_top - ((int)__brkval == 0 ? (int)&__heap_start : (int)__brkval); 
}

Serial.println(freeRam());

memory leak in Ethernet.cpp

The Ethernet library has a memory leak (for version arduino-1.0.1). Each call to EthernetClass::begin will create a new DhcpClass. The _dhcp member variable is never deleted, so each subsequent call to EthernetClass::begin will leak about 100 bytes. It takes about 10 calls to EthernetClass::begin to cause the Atmega328 to run out of memory. My patch simply checks if _dhcp was already allocated; if allocated then it reuses the previously allocated _dhcp. This may not be the best way to handle this case, but it works in my application and it seems to not cause any trouble in the examples included with the Ethernet library..

$ diff -up Ethernet.cpp Ethernet-noah.cpp 
--- Ethernet.cpp	2012-03-11 14:30:32.000000000 -0700
+++ Ethernet-noah.cpp	2012-07-30 19:25:24.353578643 -0700
@@ -10,8 +10,9 @@ uint16_t EthernetClass::_server_port[MAX
 
 int EthernetClass::begin(uint8_t *mac_address)
 {
-  _dhcp = new DhcpClass();
-
+   if (_dhcp == NULL) {
+     _dhcp = new DhcpClass();
+   }
 
   // Initialise the basic info
   W5100.init();
@@ -89,6 +90,8 @@ int EthernetClass::maintain(){
         break;
     }
   }
+// else maybe do something if _dhcp is NULL?
+
   return rc;
 }

Arduino Ethernet MAC/IP Address tester

/*
  MAC and IP address hog
  
  This sketch repeatedly requests MAC addresses from DHCP.
  A new MAC address is given for each request.
  Circuit:
  * Ethernet shield attached to pins 10, 11, 12, 13
 
  created 2012-07-25
  by Noah Spurrier
 */

#include <SPI.h>
#include <Ethernet.h>
#include <IPAddress.h>

// MAC address template.
// Note that this is a "locally administered MAC address".
// Note that the following is true: "0x4e|0x02 == 0x4e"
byte mac[] = { 0x4e, 0x4f, 0x41, 0x48, 0x0, 0x0 };
IPAddress local_ip;

void setup() {
  // Open serial port.
  Serial.begin(9600);
  // Wait for serial port to connect. Needed for Leonardo only.
  while (!Serial) ;

  delay (1000); 
  Serial.println();
  Serial.println("Begin hogging MAC:IP address leases on DHCP.");
  for (mac[4] = 0; mac[4] <= 254; mac[4]++){
    for (mac[5] = 0; mac[5] <= 254; mac[5]++){ 
      Serial.print("MAC: ");
      for (byte thisByte = 0; thisByte < 6; thisByte++) {
        // print the value of each byte of the MAC address:
        Serial.print(mac[thisByte], HEX);
        if (thisByte < 5) Serial.print(":");
      }
      Serial.print(", ");
      Serial.print("IP: ");
      // Start new Ethernet connection. See http://arduino.cc/it/Reference/Ethernet
      // Don't forget to patch Ethernet.cpp to get rid of a memory leak.
      // Without this patch, this sketch will only run for 10 or 15 loops.
      if (Ethernet.begin(mac) == 0) {
        Serial.print("ERROR: Failed to get IP address from DHCP.");
        delay(1000);
      }
      else {
        local_ip = Ethernet.localIP();
        for (byte thisByte = 0; thisByte < 4; thisByte++) {
          // print the value of each byte of the IP address:
          Serial.print(local_ip[thisByte], DEC);
          if (thisByte < 3) Serial.print("."); 
        }
      }
      Serial.println();
    }
  }
}

void loop() {

}