Difference between revisions of "Arduino notes"

From Noah.org
Jump to: navigation, search
m
m (Analog input -- hall effect sensor)
 
(8 intermediate revisions by the same user not shown)
Line 49: Line 49:
 
</pre>
 
</pre>
  
== Arduino Ethernet MAC/IP Address tester ==
+
== Arduino DHCP stress tester ==
  
 
<pre>
 
<pre>
 
/*
 
/*
   MAC and IP address hog
+
   DHCP Stress Tester
 
+
 
 
   This sketch repeatedly requests MAC addresses from DHCP.
 
   This sketch repeatedly requests MAC addresses from DHCP.
 
   A new MAC address is given for each request.
 
   A new MAC address is given for each request.
 +
 
   Circuit:
 
   Circuit:
 
   * Ethernet shield attached to pins 10, 11, 12, 13
 
   * Ethernet shield attached to pins 10, 11, 12, 13
+
 
 
   created 2012-07-25
 
   created 2012-07-25
 
   by Noah Spurrier
 
   by Noah Spurrier
 
  */
 
  */
 
 
#include <SPI.h>
 
#include <SPI.h>
 
#include <Ethernet.h>
 
#include <Ethernet.h>
 
#include <IPAddress.h>
 
#include <IPAddress.h>
  
// MAC address template.
+
// MAC address template. This is a "locally administered MAC" because
// Note that this is a "locally administered MAC address".
+
// the following is true: 0x4e|0x02 == 0x4e
// Note that the following is true: "0x4e|0x02 == 0x4e"
+
 
byte mac[] = { 0x4e, 0x4f, 0x41, 0x48, 0x0, 0x0 };
 
byte mac[] = { 0x4e, 0x4f, 0x41, 0x48, 0x0, 0x0 };
 
IPAddress local_ip;
 
IPAddress local_ip;
Line 80: Line 79:
 
   while (!Serial) ;
 
   while (!Serial) ;
  
  delay (1000);
 
 
   Serial.println();
 
   Serial.println();
   Serial.println("Begin hogging MAC:IP address leases on DHCP.");
+
  Serial.println("= Stress Test DHCP =");
 +
   Serial.println("Begin requesting 65025 MAC->IP leases from DHCP.");
 
   for (mac[4] = 0; mac[4] <= 254; mac[4]++){
 
   for (mac[4] = 0; mac[4] <= 254; mac[4]++){
     for (mac[5] = 0; mac[5] <= 254; mac[5]++){  
+
     for (mac[5] = 0; mac[5] <= 254; mac[5]++){
 
       Serial.print("MAC: ");
 
       Serial.print("MAC: ");
 
       for (byte thisByte = 0; thisByte < 6; thisByte++) {
 
       for (byte thisByte = 0; thisByte < 6; thisByte++) {
        // print the value of each byte of the MAC address:
 
 
         Serial.print(mac[thisByte], HEX);
 
         Serial.print(mac[thisByte], HEX);
 
         if (thisByte < 5) Serial.print(":");
 
         if (thisByte < 5) Serial.print(":");
Line 94: Line 92:
 
       Serial.print("IP: ");
 
       Serial.print("IP: ");
 
       // Start new Ethernet connection. See http://arduino.cc/it/Reference/Ethernet
 
       // 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) {
 
       if (Ethernet.begin(mac) == 0) {
 
         Serial.print("ERROR: Failed to get IP address from DHCP.");
 
         Serial.print("ERROR: Failed to get IP address from DHCP.");
        delay(1000);
 
 
       }
 
       }
 
       else {
 
       else {
 
         local_ip = Ethernet.localIP();
 
         local_ip = Ethernet.localIP();
 
         for (byte thisByte = 0; thisByte < 4; thisByte++) {
 
         for (byte thisByte = 0; thisByte < 4; thisByte++) {
          // print the value of each byte of the IP address:
 
 
           Serial.print(local_ip[thisByte], DEC);
 
           Serial.print(local_ip[thisByte], DEC);
           if (thisByte < 3) Serial.print(".");  
+
           if (thisByte < 3) Serial.print(".");
 
         }
 
         }
 
       }
 
       }
Line 114: Line 108:
  
 
void loop() {
 
void loop() {
 +
}
 +
</pre>
  
 +
== Phototransistor test ==
 +
 +
<pre>
 +
int val;
 +
 +
void setup() {
 +
  // Pin 13 has an LED connected on most Arduino boards:
 +
  pinMode(13, OUTPUT);   
 +
 +
  Serial.begin(9600);
 +
}
 +
 +
void loop() {
 +
  val = analogRead(0);
 +
  Serial.println(val, HEX);
 +
  val = (val < 512) ? LOW : HIGH;
 +
  digitalWrite(13, val);
 +
  delay(100); // 1/10th of a second
 +
}
 +
</pre>
 +
 +
== Analog input -- hall effect sensor ==
 +
 +
I this example I used a '''A1302''' Hall effect sensor.
 +
 +
<pre>
 +
/*
 +
    Analog Input
 +
 +
    In this example I used an A1302 Hall effect sensor.
 +
    A1302 pin1: +5V
 +
    A1302 pin2: Gnd
 +
    A1302 pin3: A0 analog in
 +
 +
    http://arduino.cc/en/Tutorial/AnalogInput
 +
*/
 +
 +
int analog_pin = A0;
 +
int analog_value = 512;
 +
 +
void setup() {
 +
    // Open serial port.
 +
    Serial.begin(9600);
 +
    // Wait for serial port to connect. Needed for Leonardo only.
 +
    while (!Serial) ;
 +
}
 +
 +
void loop() {
 +
    analog_value = analogRead(analog_pin);
 +
    Serial.print("Analog A0: 0x");
 +
    Serial.print (analog_value, HEX);
 +
    Serial.println();
 +
    delay(100);
 +
}
 +
</pre>
 +
 +
Here is a similar script, but with exponential smoothing of the data to help limit jitter noise.
 +
 +
<pre>
 +
/*
 +
    Analog Input with exponential smoothing. Often the raw output of an analog sensor
 +
    can be quite noisy. Usually you want to smooth it out a little bit.
 +
    Exponential smoothing is easier to implement than a simple average window,
 +
    and it gives better results. It is also possible to tune the amount of smoothing.
 +
 +
    In this example I used an A1302 Hall effect sensor.
 +
    A1302 pin1: +5V
 +
    A1302 pin2: Gnd
 +
    A1302 pin3: A0 analog in
 +
 +
    http://arduino.cc/en/Tutorial/AnalogInput
 +
*/
 +
 +
int analog_pin = A0;
 +
int analog_value = 512;
 +
// This stores the smooth value of the current analog_value.
 +
float analog_exp_smooth = 512.0;
 +
// The alpha variable is used to tune the exponential filter.
 +
// Basically, setting alpha to 0.1 will give a slow response;
 +
// setting alpha to 0.9 will give a fast response.
 +
// For small values of (delta t/T), alpha ~= (delta t/T).
 +
// alpha = 1-e^-(delta t/T) where t is the time between samples
 +
// and T is the time constant of the low-pass filter.
 +
float alpha = 0.2;
 +
 +
void setup() {
 +
    // Open serial port.
 +
    Serial.begin(9600);
 +
    // Wait for serial port to connect. Needed for Leonardo only.
 +
    while (!Serial) ;
 +
}
 +
 +
void loop() {
 +
    analog_value = analogRead(analog_pin);
 +
    analog_exp_smooth += alpha * ((float)analog_value - analog_exp_smooth);
 +
    Serial.print("Analog A0 raw, smoothed: ");
 +
    Serial.print (analog_value);
 +
    Serial.print(", ");
 +
    Serial.print (analog_exp_smooth, 0);
 +
    Serial.println();
 +
    delay(100);
 +
}
 +
</pre>
 +
 +
== RGB LED test ==
 +
 +
<pre>
 +
void setup() {
 +
  pinMode(9, OUTPUT);
 +
  pinMode(10, OUTPUT);
 +
  pinMode(11, OUTPUT);
 +
}
 +
 +
int red = 0;
 +
int green = 0;
 +
int blue = 0;
 +
 +
void loop() {
 +
  red = 1 + red;
 +
  green = 2 + green;
 +
  blue = 3 + blue;
 +
  if (red > 200) red = 0;
 +
  if (green > 248) green = 0;
 +
  if (blue > 255) blue = 0; 
 +
  analogWrite(9, red);
 +
  analogWrite(10, green);
 +
  analogWrite(11, blue);
 +
  delay(20);
 +
}
 +
</pre>
 +
 +
== RGB LED test V2 ==
 +
 +
<pre>
 +
void setup() {
 +
  pinMode(9, OUTPUT);
 +
  pinMode(10, OUTPUT);
 +
  pinMode(11, OUTPUT);
 +
}
 +
 +
void patrol_cycle (int *color, int *increment, int min_limit, int max_limit) {
 +
  *color = *color + *increment;
 +
  if (*color > max_limit) {
 +
    *color = max_limit;
 +
    *increment = *increment * -1;
 +
  }
 +
  if (*color < min_limit) {
 +
    *color = min_limit;
 +
    *increment = *increment * -1;
 +
  }
 +
}
 +
 +
int red = 0;
 +
int green = 0;
 +
int blue = 0;
 +
int red_inc = 1;
 +
int green_inc = 2;
 +
int blue_inc = 3;
 +
int delay_time = 2;
 +
int delay_inc = 2;
 +
 +
void loop() {
 +
  patrol_cycle (&red, &red_inc, 0, 200);
 +
  patrol_cycle (&green, &green_inc, 0, 224);
 +
  patrol_cycle (&blue, &blue_inc, 0, 255);
 +
  if (blue == 0) {
 +
    patrol_cycle (&delay_time, &delay_inc, 5, 20);
 +
  }
 +
  analogWrite(9, red);
 +
  analogWrite(10, green);
 +
  analogWrite(11, blue);
 +
  delay(delay_time);
 
}
 
}
 
</pre>
 
</pre>

Latest revision as of 17:00, 5 March 2013


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 DHCP stress tester

/*
  DHCP Stress Tester

  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. This is a "locally administered MAC" because
// 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) ;

  Serial.println();
  Serial.println("= Stress Test DHCP =");
  Serial.println("Begin requesting 65025 MAC->IP leases from 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++) {
        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
      if (Ethernet.begin(mac) == 0) {
        Serial.print("ERROR: Failed to get IP address from DHCP.");
      }
      else {
        local_ip = Ethernet.localIP();
        for (byte thisByte = 0; thisByte < 4; thisByte++) {
          Serial.print(local_ip[thisByte], DEC);
          if (thisByte < 3) Serial.print(".");
        }
      }
      Serial.println();
    }
  }
}

void loop() {
}

Phototransistor test

int val;

void setup() {
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT);     

  Serial.begin(9600);
}

void loop() {
  val = analogRead(0);
  Serial.println(val, HEX);
  val = (val < 512) ? LOW : HIGH;
  digitalWrite(13, val);
  delay(100); // 1/10th of a second
} 

Analog input -- hall effect sensor

I this example I used a A1302 Hall effect sensor.

/*
    Analog Input

    In this example I used an A1302 Hall effect sensor.
    A1302 pin1: +5V
    A1302 pin2: Gnd
    A1302 pin3: A0 analog in

    http://arduino.cc/en/Tutorial/AnalogInput
 */

int analog_pin = A0;
int analog_value = 512;

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

void loop() {
    analog_value = analogRead(analog_pin);
    Serial.print("Analog A0: 0x");
    Serial.print (analog_value, HEX);
    Serial.println();
    delay(100);
}

Here is a similar script, but with exponential smoothing of the data to help limit jitter noise.

/*
    Analog Input with exponential smoothing. Often the raw output of an analog sensor
    can be quite noisy. Usually you want to smooth it out a little bit.
    Exponential smoothing is easier to implement than a simple average window,
    and it gives better results. It is also possible to tune the amount of smoothing.

    In this example I used an A1302 Hall effect sensor.
    A1302 pin1: +5V
    A1302 pin2: Gnd
    A1302 pin3: A0 analog in

    http://arduino.cc/en/Tutorial/AnalogInput
 */

int analog_pin = A0;
int analog_value = 512;
// This stores the smooth value of the current analog_value.
float analog_exp_smooth = 512.0;
// The alpha variable is used to tune the exponential filter.
// Basically, setting alpha to 0.1 will give a slow response;
// setting alpha to 0.9 will give a fast response.
// For small values of (delta t/T), alpha ~= (delta t/T).
// alpha = 1-e^-(delta t/T) where t is the time between samples
// and T is the time constant of the low-pass filter.
float alpha = 0.2;

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

void loop() {
    analog_value = analogRead(analog_pin);
    analog_exp_smooth += alpha * ((float)analog_value - analog_exp_smooth);
    Serial.print("Analog A0 raw, smoothed: ");
    Serial.print (analog_value);
    Serial.print(", ");
    Serial.print (analog_exp_smooth, 0);
    Serial.println();
    delay(100);
}

RGB LED test

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

int red = 0;
int green = 0;
int blue = 0;

void loop() {
  red = 1 + red;
  green = 2 + green;
  blue = 3 + blue;
  if (red > 200) red = 0;
  if (green > 248) green = 0;
  if (blue > 255) blue = 0;  
  analogWrite(9, red);
  analogWrite(10, green);
  analogWrite(11, blue);
  delay(20);
}

RGB LED test V2

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void patrol_cycle (int *color, int *increment, int min_limit, int max_limit) {
  *color = *color + *increment;
  if (*color > max_limit) {
    *color = max_limit;
    *increment = *increment * -1;
  }
  if (*color < min_limit) {
    *color = min_limit;
    *increment = *increment * -1;
  }
}

int red = 0;
int green = 0;
int blue = 0;
int red_inc = 1;
int green_inc = 2;
int blue_inc = 3;
int delay_time = 2;
int delay_inc = 2;

void loop() {
  patrol_cycle (&red, &red_inc, 0, 200);
  patrol_cycle (&green, &green_inc, 0, 224);
  patrol_cycle (&blue, &blue_inc, 0, 255);
  if (blue == 0) {
    patrol_cycle (&delay_time, &delay_inc, 5, 20);
  }
  analogWrite(9, red);
  analogWrite(10, green);
  analogWrite(11, blue);
  delay(delay_time);
}