Go Back   Home > Forums > >
Home Forums Rules Articles diyAudio Store Blogs Gallery Wiki Register Donations FAQ Calendar Search Today's Posts Mark Forums Read

Analogue Source Turntables, Tonearms, Cartridges, Phono Stages, Tuners, Tape Recorders, etc.

Digital Tachometer for record player (LCD display)
Digital Tachometer for record player (LCD display)
Digital Tachometer for record player (LCD display) Please consider donating to help us continue to serve you.

Ads on/off / Custom Title / More PMs / More album space / Advanced printing & mass image saving
Reply
 
Thread Tools Search this Thread
Old 22nd June 2017, 04:34 PM   #91
tauro0221 is offline tauro0221  United States
diyAudio Member
 
Join Date: Nov 2008
Location: Victoria,TX
Hi,
.
The last skecht from Packgrog's version he has a delay of "delay(1000)" at the the end of the loop.. The delay instruction will hold timers in the Arduino system until the delay is over. Nothing will be processes. Maybe I missed the last skecht.

void loop() {
// Show waiting message after 5 seconds of no new pulses, but only if pulses were detected.
if (micros() - last_pulse_time > 5000000 && cycle_count > 0) {
lcd.setCursor(0, 1); // Set cursor at first character, second line.
lcd.print(" Awaiting Signal");
cycle_count = 0;
}
delay(1000); <<<<<<<<<<<<<<<<<<<<<<<<delay
}
  Reply With Quote
Old 22nd June 2017, 04:43 PM   #92
Packgrog is offline Packgrog  United States
diyAudio Member
 
Join Date: Jan 2015
Location: Philadelphia area
(BTW, tauro0221, if you "Go Advanced", you can wrap your code snippets in the CODE tag, so the formatting won't get borked).

My only concern with ditching the delay is that the loop comparison "if (micros() - last_pulse_time > 5000000 && cycle_count > 0)" will be running CONSTANTLY. I'm not sure if that would be a help of a hindrance constantly making so many calls to micros().
  Reply With Quote
Old 22nd June 2017, 05:17 PM   #93
Pyramid is offline Pyramid  United States
diyAudio Member
 
Pyramid's Avatar
 
Join Date: May 2006
Location: Behind the Cheddar Curtain
Quote:
Originally Posted by Packgrog View Post
So I ditched the delay in the loop, and refactored the interrupt handler to try cutting down excess calls to lcd.print(). Any thoughts on this?

Code:
// Sensor pulse completion interrupt callback handler
void calculate_rpm() {
  last_pulse_time = micros();

  if (cycle_count < 2) {
    // Build up a couple of cycles to limit poor reporting.
    cycle_count++;
    lcd.setCursor(0, 1);
    lcd.print("  RPM:          ");
  } else {
    // Avoid DIV0, just in case.
    float rpm = (last_pulse_time > prev_pulse_time) ? 60000000.0/(last_pulse_time - prev_pulse_time) : 0;
    lcd.setCursor(7, 1);
    lcd.print(rpm, 4);

    // Send update to Phoenix PSU via serial port (D0 and D1) in format XX.XXX[lf][cr]
    if ((10.0 <= rpm) && (rpm < 100)) {
      char outstr[6];
      dtostrf(rpm, 6, 3, outstr);
      Serial.print(outstr);
      Serial.print("\n\r");
    }
  }
  prev_pulse_time = last_pulse_time;
}
First things first, I moved setting prev_pulse_time = last_pulse_time to the end of the handler method, so that last_pulse_time = micros() could be the very first thing to happen in the handler, to limit the delay as much as possible. I also changed the lcd.print() functionality to limit the time spent on it, since I suspect that's likely an expensive call.

I did stumble across some comments on a potential speedup from a weird refactoring of "if ((10.0 <= rpm) && (rpm < 100))", but the code didn't really make sense to me. It seemed flat-out wrong (speed is great, but useless if functionally incorrect). I'm also not sure this would be one of the bigger fish.

I wonder if using local variables, and the corresponding creation/destruction, could add an unnecessary delay? Making all variables global goes against my coding instincts, but perhaps it could save some cycles here. I wonder if making outstr global char[8], prepopulated with the LNCR at the end, and just doing the dtostrf and single Serial.print() would save some more.

Thoughts?
The goal is to capture the count in micros as soon as the detection of the trigger event occurs. Any delays, or any CHANGES in delay from one reading to the next will cause the reading to bobble. Once the count is captured (by your last_pulse_time = micros() statement), almost nothing else will matter or change the computation, for the next 1.8 seconds at least. Any inconsistency in time vectoring to the ISR will cause the reading to vary.

If the resolution of the timer tick is 4.00S, the a count of 450,000 produces a result of 33.333 RPM. For the display to show 33.352 RPM, the count would need to be 449,748; 252 counts is a lot to be off by. It may be a combination of trigger ambiguity and software processing. One of the things I did to confirm my trigger was occurring at the same point in time every rev, was to output a very short but very bright pulse from a white LED at the time the trigger was detected. I taped a small portion of an engineer's rule (with 1/64" graduations) to the platter surface and positioned a 40 AWG wire so that it would be midway through the rule when the strobe light flashed. I then observed the trigger point on the engineer's rule at every flash (through a 10x microscope) and looked for drift or bobble from one trigger to the next. This was easier to do in assembly language and any inconsistent software delays in creating the strobe flash will exacerbate the problem, but it should tell you if your detection circuit is inconsistent or not.

As a rule, you generally want to keep the ISR as short as possible. Your doing the calculation and output in the ISR probably doesn't adversely affect the outcome, but I perfer to use flags to signal the main loop to do all the processing and output. YMMV.
  Reply With Quote
Old 22nd June 2017, 05:20 PM   #94
Pyramid is offline Pyramid  United States
diyAudio Member
 
Pyramid's Avatar
 
Join Date: May 2006
Location: Behind the Cheddar Curtain
Quote:
Originally Posted by Packgrog View Post
(BTW, tauro0221, if you "Go Advanced", you can wrap your code snippets in the CODE tag, so the formatting won't get borked).

My only concern with ditching the delay is that the loop comparison "if (micros() - last_pulse_time > 5000000 && cycle_count > 0)" will be running CONSTANTLY. I'm not sure if that would be a help of a hindrance constantly making so many calls to micros().
You could use a different call to millis() if this was a concern (assuming this uses a different timer than micros().

The difference in 33.333 and 33.352 RPM is ~1mS (252 counts x 4S).
  Reply With Quote
Old 22nd June 2017, 05:23 PM   #95
Pyramid is offline Pyramid  United States
diyAudio Member
 
Pyramid's Avatar
 
Join Date: May 2006
Location: Behind the Cheddar Curtain
I'm fairly new to the Arduino, but one of the questions I had for a friend of mine who has programmed them for a while: Which of the 3 timers does micros() use? If I write my own routine to increment a count every xx.xS and I use the same timer, what happens? What happens when you attempt to assign a priority to an ISR that is already in use by micros() or millis()?

Unfortunately, I haven't been able to find any answers.
  Reply With Quote
Old 22nd June 2017, 05:55 PM   #96
Packgrog is offline Packgrog  United States
diyAudio Member
 
Join Date: Jan 2015
Location: Philadelphia area
Quote:
Originally Posted by Pyramid View Post
As a rule, you generally want to keep the ISR as short as possible. Your doing the calculation and output in the ISR probably doesn't adversely affect the outcome, but I perfer to use flags to signal the main loop to do all the processing and output. YMMV.
Not a bad idea there. Probably wouldn't make a difference in the time capturing accuracy, but also probably a worthwhile exercise.
  Reply With Quote
Old 22nd June 2017, 06:20 PM   #97
tauro0221 is offline tauro0221  United States
diyAudio Member
 
Join Date: Nov 2008
Location: Victoria,TX
Hi,
The reason why I use the 3 pulse interrupt it is to be ready to wait for the interrupt in the routine. This will remove the delay of the interrupt branch time service. It will give you a more steady Rpm ready from the sensor.
  Reply With Quote
Old 22nd June 2017, 06:31 PM   #98
Packgrog is offline Packgrog  United States
diyAudio Member
 
Join Date: Jan 2015
Location: Philadelphia area
I'm not sure whether the 3 pulse check is necessary, as you're ultimately only checking the speed difference every third pulse. However, your approach captured the micros(); value sooner (I suspect that the case statement is faster than an assignment), and your interrupt handler was much smaller, doing the bulk of the processing in the loop. I've changed it to be more like yours, as per Pyramid's suggestion. Perhaps that will provide better results.

I will say one thing for your approach, tauro0221: The speed calculations were much closer to what I expected, and matched more closely to the Turntabulator reading. Who knows, maybe it's just delay from trying to do "prev_pulse_time = last_pulse_time" before "last_pulse_time = micros()", and none of the other changes matter for speed accuracy. Or maybe the collection of changes will add up to overall better efficiency as well.
  Reply With Quote
Old 22nd June 2017, 06:41 PM   #99
tauro0221 is offline tauro0221  United States
diyAudio Member
 
Join Date: Nov 2008
Location: Victoria,TX
Hi,
Also I do the calculation after the capture of the 2 time.
  Reply With Quote
Old 22nd June 2017, 07:20 PM   #100
Packgrog is offline Packgrog  United States
diyAudio Member
 
Join Date: Jan 2015
Location: Philadelphia area
Here's some tweaks to offload the bulk of the work to the loop, and grab micros() first and foremost in interrupt handler. Perhaps the size of the ISR last time was causing further delay just from loading the function. Updating only 2 tiny global variables is about as small as I'm going to be able to get that.

It's been a long time since I had to be this nitpicky with code time sensitivity.
Attached Files
File Type: txt diyaudio_ostrich_tach_2.txt (2.8 KB, 43 views)
  Reply With Quote

Reply


Digital Tachometer for record player (LCD display)Hide this!Advertise here!
Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Digital Turntable Tachometer and DDS based PSU Pyramid Vendor's Bazaar 234 6th November 2017 01:57 AM
The new 5-Record-Player.... M_Balou The Lounge 5 18th October 2016 11:38 PM
Old record player Rucyrius Everything Else 0 24th March 2011 03:35 PM
Change old cd player display to LCD, easy? Tubeee Digital Source 0 7th December 2003 12:03 PM


New To Site? Need Help?

All times are GMT. The time now is 06:25 PM.


Search Engine Optimisation provided by DragonByte SEO (Pro) - vBulletin Mods & Addons Copyright © 2020 DragonByte Technologies Ltd.
Resources saved on this page: MySQL 15.00%
vBulletin Optimisation provided by vB Optimise (Pro) - vBulletin Mods & Addons Copyright © 2020 DragonByte Technologies Ltd.
Copyright ©1999-2020 diyAudio
Wiki