Basic A3144 TACHO for machine tool?

Hi, i have been trting to put together a basic tachometer using an A3144 Hall effect sensor, an arduino NANO and a 7 segment/8DIGIT MAX7219 display, im pretty poor when it comes to actual coding so ive been using information gleaned from the following gihub page....

And the code...


// Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012
// http://www.mikrocontroller.net/attachment/189505/Drehzahlmesser.ino
// some changes by Nicu FLORICA (niq_ro) - see movie from https://youtu.be/9jCCoyg4wmA

// source for LEDControl: http://embedded-lab.com/blog/?p=6862
#include "LedControl.h" // https://github.com/wayoda/LedControl
/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin 12 is connected to the DataIn 
 pin 11 is connected to the CLK 
 pin 10 is connected to LOAD 
 We have only a single MAX72XX.
 */
LedControl lc=LedControl(12,11,10,1);
int vtot, vs, vsz, vz, vzu, vu, vv;

// Input: Pin D2

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// here on rising edge
void isr () 
{
  unsigned int counter = TCNT1;  // quickly save it
  
  // wait until we noticed last one
  if (triggered)
    return;

  if (first)
    {
    startTime = (overflowCount << 16) + counter;
    first = false;
    return;  
    }
    
  finishTime = (overflowCount << 16) + counter;
  triggered = true;
  detachInterrupt(0);   
}  // end of isr

// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect) 
{
  overflowCount++;
}  // end of TIMER1_OVF_vect


void prepareForInterrupts ()
  {
  // get ready for next time
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  first = true;
  triggered = false;  // re-arm for next time
  attachInterrupt(0, isr, RISING);     
  }  // end of prepareForInterrupts
  

void setup () 
  {
  Serial.begin(115200);       
  Serial.println("Frequency Counter");
  
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  // Timer 1 - interrupt on overflow
  TIMSK1 = bit (TOIE1);   // enable Timer1 Interrupt
  // zero it
  TCNT1 = 0;  
  overflowCount = 0;  
  // start Timer 1
  TCCR1B =  bit (CS20);  //  no prescaling

  // set up for interrupts
  prepareForInterrupts ();   
  
  // Initialize MAX7219 device
lc.shutdown(0,false); // Enable display 
lc.setIntensity(0,8); // Set brightness level (0 is min, 15 is max) 
lc.clearDisplay(0); // Clear display register 

lc.setChar(0,7,' ',false);// ma asigur ca nu e nimic pe coloana 7 (cea din stanga) 
lc.setRow(0,6,B1100010);  // afisez litera "n" pe coloane 6
lc.setRow(0,5,B0100000);  // afisez litera "i" pe coloane 5
lc.setRow(0,4,B1110011);  // afisez litera "q" pe coloane 4
lc.setRow(0,3,B0000001);  // afisez semnul "-" pe coloane 3
lc.setRow(0,2,B1000010);  // afisez litera "r" pe coloane 2
lc.setRow(0,1,B1100011);  // afisez litera "o" pe coloane 1
lc.setChar(0,0,' ',false);// ma asigur ca nu e nimic pe colanea 0 (din dreapta)
delay(2000);
lc.clearDisplay(0); // Clear display register    
  
  } // end of setup

void loop () 
  {

  if (!triggered) 
  return;
 
  unsigned long elapsedTime = finishTime - startTime;
//  float rpm = 60 * F_CPU / float (elapsedTime);  // each tick is 62.5 nS at 16 MHz
  float rpm = 30 * F_CPU / float (elapsedTime);  // each tick is 62.5 nS at 16 MHz
 
    
    Serial.print ("RPM: ");
    Serial.println (rpm);
  vtot = rpm;

// calculate number for each figure number
vs = vtot /1000;
vsz = vtot - 1000*vs;
vz = vsz /100;
vzu = vsz - 100*vz;
vu = vzu /10; 
vv = vzu - 10*vu; 
//vtot = 0;
lc.setChar(0,7,' ',false); 
//lc.setRow(0,7,B00111110);  // afisez litera "U" pe coloana 7
lc.setChar(0,6,' ',false); 
lc.setChar(0,5,' ',false); 
//lc.setRow(0,5,B00001001);  // afisez "=" pe coloana 5
lc.setChar(0,4,' ',false); 
if (vs == 0) lc.setChar(0,3,' ',false); else
lc.setDigit(0,3,vs, false); // afisez miile pe coloana 3
lc.setDigit(0,2,vz, false); // afisez sutele pe coloana 2
lc.setDigit(0,1,vu, false); // afisez zecile pe coloana 1
lc.setDigit(0,0,vv,false); 
 //  }
  
  //Serial.print ("Took: ");   // Ausgabe der gezählten counts
  //Serial.print (elapsedTime);
  //Serial.print (" counts. ");

  // so we can read it  
  delay (500);

  prepareForInterrupts ();   
}   // end of loop

I have the DIN, LOAD/CS and CLK connected to D12, D10 and D11 respectivley, and the DATA pin from the A3144 to D2 on the NANO as mentioned in a comment in the code.
Now, when ive tried the 3144 alone with a LED/resistor to confirm its functioning its fine, its high until magnets close, when close it goes low its all good.
but when i wire it up with the arduino/MAX7219 something isnt correct. a magnet near the 3144 makes no diference whatsoever, when the code is first uploaded it boots up and displays 'niq_ro' - but after that the display is either blank, with no reaction to the presence of a magnet, or it throws up seemingly random numbers, reset the NANO and it just does the same :confused: the code compiles and uploads fine in the IDE

Now like i said im a beginner when it comes to coding, i usually come back to the arduino when i have a use for it, learn enough to get me through a basic project like this then forget it all by the time the next project comes around, but i would really like to learn more and become slightly more proficient in C++, i started trying to look at the code logically, and allthough it mentions the DATA from the 3144 in a comment, surely that is ignored due to the //? other than that it doesnt explicitly define D2 as the DATA line from 3144 :confused: ? im 99% sure im being a fool here and am about to feel foolish, but if it helps me to learn then im willing to accept it lol.
Can someone please help with where im going wrong and point me in the right direction.
any info or advice would be greatly appreciated, and apologies for rambling :slight_smile:
cheers,
josh

Please express this using pen, paper and a photo of the schematcs.

terribly sorry im afraid i dont know how to rotate it lol :confused: but hopefully you get the gist? please ignore the pin positions on the NANO theyre obviously not accurate in terms of location

The hall effect is an open collector device and requires a resistor from signal to positive rail.

ah ok, so it will not function without ? i will give that a go first thing, what kind of value would you recomend?

The first thing you can try to get you going is to set the pinmode for pin2 to INPUT_PULLUP. This will use a 20-50K internal resistor.

The interrupt will be more immune transients if the pullup is stronger. That is, use an external pull up of 4.7K or 2.2K.

You can use an LED along with an appropriately sized rezistor for the voltage you are using( not shown in your pencil diagram) or just say a 4k7 resistor.

That's okey. Where does the 5 volt to the 7219 come from? From the controller might be questionable depending on the current needed.

so far its been supplied 5V from the NANO 5V pin, the DATASHEET specifies a operating supply current of 330mA with all segments and decimal lit, obviousy i wont be drawing that much on average, but would it be worth supplying it from a separate 5V supply?

Ah ok great, will give these a go in the morning :slight_smile: in terms of the code does everything look ok? if it is could you explain how the arduino 'knows' that PIN D2 is to recieve signals? (im autistic and always try to understand rather than just accept lol)

https://www.arduino.cc/reference/cs/language/functions/external-interrupts/attachinterrupt/

On the Nano you are using, interrupt 0 is on pin 2. This is defined in the "board package" behind the code.

The preferred syntax for your case would be
attachInterrupt(digitalPinToInterrupt(2), isr, RISING);

this is the part im curious about...

// Input: Pin D2

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

presumably here is where i would want to insert - pinMode(INPUT_PULLUP)?

ah ok, do if not specifically defined as something else, its default setting is as an interupt pin?

No. pinMode() goes in setup().

https://docs.arduino.cc/language-reference/en/functions/digital-io/pinMode/

https://docs.arduino.cc/learn/microcontrollers/digital-pins/

The basic tutorial on interrupts is here.

You are using the external interrupts available on pin2 and 3.

What RPM range are you expecting? How many pulses per revolution?

1 Like

How is the Nano powered?

either via the USB-C from my laptop, or after ive uploaded the sketch then via a 2A USB-C outlet on the wall

ideally an RPM range of 50 - 3000 RPM but realisticly the ill rarely use the outer borders of that spectrum, more commonly 200 - 2500. in terms of pulses per rev, im intending to have 1 Neodynium magnet mounted on the spindle pulley, so presumably that would be one pulse per rev? (please correct me if im missing something though lol)

1 Like

That sounds safe. I hope the 2 GNDs are connrcted.