Learning Arduino, MAX7219, and RPM at a motor

Hello everyone.
Fairly new/returning back to embedded after a 10 year hiatus and a rough higher-ed experience. Anyway, the drive to put some use to a stash of HP 5082 bubble style displays caught my attention, and I had a few MAX7219's sitting around. Within analog territory, I have this buttoned up pretty well and I was able to determine the approximate counts-per-second/1000RPM from a motor with tach wires attached in. See attached schematic for what I tried to do (Sorry image is small I guess). Basically just an opamp that takes in the sine-ish tach and converts to a square wave at approx. 130Hz/1000RPM.

As far as learning how to use the MAX7219, I've learned how to get it to count at a steady rate and countdown from 99999 at a one second rate. That's about it; however I was able to get that chip to turn on and display stuff. Some basic C-language rules I know and remember a little but I'm getting pretty stuck as far as what to do next:

I get: we can only take so many snapshots at the relative counts per second. We then take that, do some math, and then return that value somehow. Keyword: "somehow." How to implement this at all in code I'm completely lost. I found this however that seems to kinda be on the right track (Courtesy the original author). Doesn't work when I uploaded it but some of it seems familiar or maybe can be worked out and fixed? Should I just start over fresh? Either way I need some help from a community of people far better at this than I am. Any help is greatly appreciated. If I messed up on putting this message together I'll try to fix it.

So somehow this has an overall "sample time" it "sniffs" the tach before looping around thru some math. Leaving hz as counts per second uh I'm thinking we need to know this to a finer division but is this because most of the time at a mcu point, time is counted in microseconds? Would I need some sort of _ _ _ (ones), _ _ tens_, etc. to be crafted up? I think I can get this just need a little guidance on the coding of something like this.

// 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,4,' ',false); 
//lc.setRow(0,4,B00111110);  // afisez litera "U" pe coloana 7
//lc.setChar(0,3,' ',false); 
//lc.setChar(0,2,' ',false); 
//lc.setRow(0,4,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
1 Like

// 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);
byte  vs,  vz,  vu, vv;

// Input: Pin D2

void setup () {
  Serial.begin(115200);
  Serial.println("Frequency Counter");

  // 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.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
  pinMode(2, INPUT_PULLUP);
} // end of setup

void loop () {
  unsigned long elapsedTime = millis();
  while (digitalRead(2)) {
    if (millis() - elapsedTime > 2000) {
      elapsedTime = 0;
      break;
    }
  }
  if (elapsedTime) {
    elapsedTime = millis();
    while (!digitalRead(2)) {
      if (millis() - elapsedTime > 2000) {
        elapsedTime = 0;
        break;
      }
    }
  }
  if (elapsedTime)elapsedTime = millis() - elapsedTime;

  float rpm = 60000.0 / float (elapsedTime);  // each tick is 62.5 nS at 16 MHz

  Serial.print ("RPM: ");
  Serial.println (rpm);

  // calculate number for each figure number
  vs = (rpm / 1000) % 10;
  vz = (rpm / 100) % 10;
  vu = (rpm / 10) % 10;
  vv = rpm % 10;

  lc.setChar(0, 3, vs ? 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);
}   // end of loop

1. If you want to show the RPM on MAX7219 driven 4-digit 7-segment diaply unit, you may follow this schematic (Fig-1):
max7219-4Digit
Figure-1:

If you like, you can use the following MAX7219 based assembled display unit:
max72194DigitAssembled
Figure-2:

2. Use TCNT1/TC1 of Arduino UNO to count the incoming pulses (130 Hz/1000 RPM) for a minute and show it on the display unit.

How do I do "count the incoming pulses (130 Hz/1000 RPM) for a minute and show it on the display unit?" The coding aspect of this I'm really struggling with I'm sorry. Was that what was in the code in the prior message by @kolaha? also verification of your code results in errors and I'm not sure what do to there to fix them. Sorry again here folks I don't know code.
I have connectivity to the display. That has been all good and working as just a count down timer but that was something I barely knew how to do.

Please, show a hand drwan circuit among UNO, MAX7219 and Display Unit.

How have you made the display unit -- have you put discrete component or display unit like Fig-2 of 3?

uint16_t rpm = 60000 / elapsedTime;

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.