Arduino Snippets: Hall Effect Sensor

Attaching a linear Hall effect sensor to an Arduino doesn’t require much effort at all:

Linear Hall Sensor

Linear Hall Sensor

Despite what I observed on that breadboard lashup, the output will need a load resistor (output-to-ground, across pins 3 and 2) if there’s no internal constant-current sink; anything around 10 kΩ should suffice. The one I have works fine with or without the resistor; I added a 10 KΩ resistor that’s not shown here. The output voltage does, as you’d expect, change slightly with the resistor in place.

The sensor lives on a different part of the same breadboard now:

49E Linear Hall Effect Sensor - breadboard

49E Linear Hall Effect Sensor – breadboard

The test code drives the RGB LED strip: red for positive field strength and blue for negative. The maximum and minimum values track the extremes, for plenty of color regardless of how weak a magnet it sees. It works great with the one on my fingernail… and random screwdrivers, digital calipers, scissors, and suchlike.

The OpenSCAD source code:

// Hall sensor
// Ed Nisley - KE4ANU - November 2012

//----------
// Pin assignments

const byte PIN_RED = 9;				// PWM - LED driver outputs +active
const byte PIN_GREEN = 10;
const byte PIN_BLUE = 11;

const byte PIN_FIELD = A0;			// Hall sensor input, 0 field = 2.5 v, more or less

const byte PIN_HEARTBEAT = 13;		// DO - Arduino LED

//----------
// Constants

const int UPDATEMS = 5;					// update LEDs only this many ms apart

#define TCCRxB 0x02						// Timer prescaler

//----------
// Globals

float FieldHigh, FieldLow, FieldRange, FieldBase, Field;

byte Red,Blue,Green;

unsigned long MillisNow;
unsigned long MillisThen;

//-- Helper routine for printf()

int s_putc(char c, FILE *t) {
  Serial.write(c);
}

int sign_float(float val) {
	if (val < 0.0)
		return -1;
	else if (val > 0.0)
		return 1;

	return 0;
}

//-- Sample magnetic field with a dab of averaging

#define FIELDAVERAGE 5

float ReadSensor(byte Pin) {
float Field;

	Field = (float)analogRead(Pin);
	for (byte i = 1; i < FIELDAVERAGE; i++)
		Field += (float)analogRead(Pin);

	return Field / (FIELDAVERAGE * 1024.0);
}

//------------------
// Set things up

void setup() {
  pinMode(PIN_HEARTBEAT,OUTPUT);
  digitalWrite(PIN_HEARTBEAT,LOW);	// show we arrived

  TCCR1B = TCCRxB;					// set frequency for PWM 9 & 10
  TCCR2B = TCCRxB;					// set frequency for PWM 3 & 11

  pinMode(PIN_RED,OUTPUT);
  analogWrite(PIN_RED,0);			// force gate voltage = 0

  pinMode(PIN_GREEN,OUTPUT);
  analogWrite(PIN_GREEN,0);

  pinMode(PIN_BLUE,OUTPUT);
  analogWrite(PIN_BLUE,0);

  Serial.begin(9600);
  fdevopen(&s_putc,0);				// set up serial output for printf()

  printf("Hall effect sensor\r\nEd Nisley - KE4ZNU - November 2012\r\n");

  Field = ReadSensor(PIN_FIELD);	// prime the field sensor pump
  FieldBase = Field;
  FieldHigh = 1.1 * Field;
  FieldLow = 0.9 * Field;
  FieldRange = FieldHigh - FieldLow;

  printf("Average field: %d\n",(int)(1024.0 * Field));

  MillisThen = millis();

}

//------------------
// Run the test loop

void loop() {

	MillisNow = millis();

	if ((MillisNow - MillisThen) > UPDATEMS) {
		digitalWrite(PIN_HEARTBEAT,HIGH);

		Field = ReadSensor(PIN_FIELD);
		FieldHigh = max(FieldHigh,Field);
		FieldLow = min(FieldLow,Field);
		FieldRange = FieldHigh - FieldLow;

//		printf("Field: %d\n",(int)(1024.0 * Field));

		switch (sign_float(Field - FieldBase)) {
			case -1:
				Blue = (byte)(255.0*(FieldBase - Field)/FieldRange);
				Red = 0;
				break;
			case 1:
				Red = (byte)(255.0*(Field - FieldBase)/FieldRange);
				Blue = 0;
				break;
			case 0:
				Red = Blue = 0;
				break;
			default:
				printf("Whoops!\n");
				delay(1000);
		}
		Green = 0;

		analogWrite(PIN_RED, Red);
		analogWrite(PIN_BLUE,Blue);
		analogWrite(PIN_GREEN,Green);

		digitalWrite(PIN_HEARTBEAT,LOW);

		MillisThen = MillisNow;
	}

}

About these ads