i would like to use Arduino as a pulse divider by 6 for counting a turbine RPM that has 6 blades and a pulse coming per blade.
meaning for each 6 pulse inputs i need to output 1 pulse.
this can be done by HW but i have arduinos available and they are cheap enough
the input signal is about 690,000 per minute, or 11,500 per second, or 11.5Khz. not extremely fast for software i believe.
i was thinking about an ISR reading the rise and fall edge of the pin and then in the main loop when we reach 6 run the pulse and init the counter.
any other ideas?
and code examples / implementations available?
If it's a known fixed width, then there is no need to measure it in the code.
Servicing interrupts that occur within 50usec of each other may be a little tricky just using arduino functions.
the width is not permenant, its a spinning turbine so width is RPM dependant.
Actually, lets do some calculations together:
turbine max RPM = 120K RPM. and the turbine has 6 blades. each blase in front of the sensor creates an ON signal and no blade = OFF signal.
With 6 blades we have 720K pulses per minute, and 12,000 pulses per second.
Also, a full turbine revolution takes ~500us.
Assuming the width of the 6 blades "cover" around 10% of the turbine diameter therefore all 6 blades (ON state time) is about 50us for all 6, or each lets round to around 8us.
that would mean the signal will look like this in one full revolution:
8us ON
75us OFF
8us ON
75us OFF
8us ON
75us OFF
8us ON
75us OFF
8us ON
75us OFF
8us ON
75us OFF
Your numbers are correct but that 8usec will be a problem.
Timing estimates for just doing a digitalWrite range from 3.5us to 10us
Interrupt latency could be 3 to 5usec.
If you write the code using direct register manipulation, i.e. writing directly to the 328 regisers and not using any Arduino functions it would be possible. How much experience do you have in this regard?
Connect the input to both interrupt pins 2 and 3 on an UNO.
Set one ISR for Rising edge to count the pulses and one for Falling just to know when the pulse ends.
So on the sixth Rising edge set the output High and when the Falling edge ISR occurs set the output Low
i need to utilize it on a small lightweight board such as pro mini as its going into a small RC jet. i think UNO and pro mini both use tbe same atmel 328p?
i have no knowledge of writing to registers. happy to get any help in that regard.
If pulse width isn't important, then you could use one of the 8-pin TINY devices to generate a nice square wave. I use TINY85's to generate baud rate clocks by dividing down an external system clock.
From memory it's Timer0 on a TINY85. You can feed in the external clock and use the hardware counter of Timer0 to toggle the associated output compare pin. This can all be done in hardware and once configured requires no further software involvement - i.e. no interrupt handlers or pin toggling needed.
Here's my complete code for my 8085 micro where the TINY85 handles the processor reset and divides the system clock down to create the baud rate clock for my UART:
// 8085 System reset & baud rate clock generator / divider
//
// PB0 : Timer / Counter 0 compare match A output - i.e. baud rate clock
// PB2 : Timer / Counter 0 clock source from 8085 system clock
// PB4 : drives the 8085 RESET line LOW for 100mS on TINY85 RESET.
#define BAUD_CLOCK PIN_PB0 //OC0A
#define SYS_CLK_85 PIN_PB2 // T0 CLK IN
#define RESET_85 PIN_PB4
void setup() {
Serial.begin(9600);
// set all the pins as outputs
pinMode( SYS_CLK_85, INPUT );
pinMode( BAUD_CLOCK, OUTPUT );
pinMode( RESET_85, OUTPUT );
// drive the 8085 RESET lines LOW
digitalWrite( RESET_85, LOW );
// delay for 100mS
delay( 100 );
// drive the 8085 RESET lines HIGH
digitalWrite( RESET_85, HIGH );
// TIMER / COUNTER 0 is repurposed here so the millis() and delay()
// functions that rely on Timer 0 no longer work.
TIMSK = 0; // disable any timer interrupts
TCCR0B = 0; // stop Timer 0
// Configure Timer 0 to count clock pulses on the T0 pin (i.e. PB2)
// in CTC mode toggling OC0A on a Compare Match.
TCCR0A = B01000010;
TCCR0B = B00000110;
// Seems that setting the TNCT0 initial value and the
// OCR0A should be done last otherwise strange things happen!!!
TCNT0 = 0; // initialise Timer 0 to 0 - counts up
// NOTE: 1 complete cycle of OC0A is 2 compare matches of OCR0A
// For an 8085 crystal of 3.6864MHz, the CPU CLK OUT is 1.8432MHz (i.e half)
// To get 9600Hz out, the timer has to count 00..95 twice.
OCR0A = 95;
GTCCR = B00000001;
}
void loop() {
// nothing to do - hurrah!
}