The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Day: December 10, 2012

  • 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;
    	}
    
    }