So I have not found any references to digital to digital conversion. Or in other words, I am receiving one frequency and changing it to another with an equation. I have been working with an Arduino Mega, the code will pick up the signal and tell me the rpm conversion but it will not output the new signal correctly. This may be a hardware issue but I could also be up in the night with my coding.
any suggestion would be welcome.
Here is a sample code:
#include <Wire.h>
long unsigned int S1, N1, S2, N2;
long unsigned int TS,TH,Tm,T1;
int hd;
int leds=25;
int ledJ=13;
byte senI1 = 1; // 0,1,2,3,4,5 = digital pin 2,3,21,20,19,18
byte sPin = 3;
long unsigned int Cl;
long unsigned int M1, M2;
unsigned int PC;
int Knob, Ti;
int sigJ=10 ;
float rpm;
int cal =6;
void setup() {
Serial.begin(9600);
pinMode(leds, OUTPUT);
digitalWrite(leds,LOW);
pinMode(ledJ, OUTPUT);
digitalWrite(ledJ,LOW);
pinMode(sigJ, OUTPUT);
digitalWrite(sigJ,LOW);
N1=0;
rpm=0.00;
hd=1;
TS=0;
TH=0;
Cl=0;
attachInterrupt(senI1, C1f, RISING);
}
void loop() {
//Serial.println(Cl);
if(Cl >= 5*cal){
S1=millis();
Tm=(S1-N1);
rpm = ((60000/Tm)*Cl)/cal;
Serial.println(Cl);
T1=(Tm/5)*(2*PI);
TH=(2/3)*PI*T1;
TS=TH/30;
Serial.println(TS);
Serial.print("RPM :");
Serial.println(rpm);
rpm=0;
Cl=0;
N1=millis();
Ti=0;
}
Serial.println(TH);
//TH=100000;// for testing
//TS=TH/30;
S2=millis();
N2= S2;
hd=1;
while((N2-S2)<=TH){
if(hd == 1){
for (int i=0; i<4; i++){
M1=millis();
M2=M1;
while((M1-M2)<=TS){digitalWrite(sigJ,HIGH);digitalWrite(ledJ,HIGH); M1=millis(); }
M2=M1;
while((M1-M2)<=(TS*4)){digitalWrite(sigJ,LOW);digitalWrite(ledJ,LOW); M1=millis(); }
M2=M1;
}
hd =0;
}
N2=millis();
}
}
//////////////////////function/////////////////////
void C1f()
{
// Increment the pulse counter
Cl++;
}
can you give us a sample of the output you are getting and what results you would expect?
also try printing some more variable values such as Tm T1 TH etc
possibly change your calculations to use float variables?
Thanks, I made the Cl a volatile int; however, this did not change the output, unfortunately. I will work on the variable names I am in the military and everything is an acronym to us so I do it with my variables. They all mean something to me just hard to translate for others .
The output that I am getting from this code is a square wave that has for short highs followed by a long low, at a constant frequency. It doesn't change frequency as the input frequency changes. So I put in 4kHz and I get out about 0.5Khz, I put in 16kHz and I get out 0.5kHz, no change.
I am thinking it is the loop but it may also be that the Arduino is not capable of the speed, I just purchased a DUE but it is doing the same thing but at a faster rate. I put in 4kHz and I get out 20Khz, I put in 16kHz and I get out 20Khz.
The signal I put in is a simple square wave from 0.4kHz to 20kHz.
And Yes this is a signal conversion for a vehicle rpm sensor, but I am hoping to do more once I get this down.
The conversion for the frequency is in the for loop of the code. Fist I need the time for one rotation of the engine which with my code it 6 pulses so at 4kHz this would be 15 milliseconds. This time is T1 in my code. THe out signal is high for 1/30 of 2/3 PI, low for 4/30 then high again for a total of four pulses then a long pause for 14/30, this is repeated three times for the time T1. So for one cycle T1 is divided by 18. So the pulse frequency at 4kHz is 12kHz or 1/(T1/18) or simply 3* input frequency I just need the pulse length adjustment and pauses. SO I just use the short time (TS) for my while loop timing for the output signal.
you are attempting to measure a frequency, say 4KHz, and then generate all the other signals from that
have a look at the attached image
It shows a 4KHz signal (CH1 yellow trace generated by a Uno) which is measured by a Mega which then generates a signal 3 times the measured (CH2 blue trace) you can see the CH2 freq is 12.08KHz
horace yes that is exactly what I am trying to do and the signal you generated is very similar really just missing the long pause after every fourth pulse from the mega.
I have tried using micros() instead of millis() which once the signal gets fast enough will be necessary, but I have not yet produced an output that follows the input.
have you managed to measure the frequency with reasonable accuracy?
the following code (using a mega) uses timer1 to measure the number of clock pulses between each rising interrupt on pin 2
// measure frequency on pin using timer1 counter
#define PIN 2 // must be interruptable!
// Timer 1 setup Xtal = 16 Mhz
void Init_Timer1(void)
{
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; //initialize counter value to 0
TCCR1B |= (1 << CS10); // Set CS10 bits for Zero prescaler
}
void setup() {
Serial.begin(9600);
// attach interrupt to pin use rising edge
attachInterrupt(digitalPinToInterrupt(PIN), Trig, RISING);
Init_Timer1(); //initialise timer1
}
// pin change interrupt handler
volatile unsigned int timer;
void Trig() {
timer=TCNT1; // note TCNT1 counter
TCNT1=0;
}
// display the frequency
void loop() {
delay(1000);
unsigned int timerCopy=timer;
Serial.print("timer= ");
Serial.print(timerCopy);
// calculate frequency, assume 16MHz clock - allow for calling function
unsigned int frequency=16000000UL/(timerCopy-80);
Serial.print(" frequency Hz = ");
Serial.println(frequency);
}
a run with input signals from 500Hz to 8KHz
timer= 32045 frequency Hz = 500
timer= 32044 frequency Hz = 500
timer= 16069 frequency Hz = 1000
timer= 16083 frequency Hz = 999
timer= 8049 frequency Hz = 2007
timer= 8049 frequency Hz = 2007
timer= 4188 frequency Hz = 3894
timer= 4083 frequency Hz = 3997
timer= 4087 frequency Hz = 3993
timer= 2078 frequency Hz = 8008
timer= 2083 frequency Hz = 7988
DavidAsh:
The conversion for the frequency is in the for loop of the code. Fist I need the time for one rotation of the engine which with my code it 6 pulses so at 4kHz this would be 15 milliseconds. This time is T1 in my code. THe out signal is high for 1/30 of 2/3 PI, low for 4/30 then high again for a total of four pulses then a long pause for 14/30, this is repeated three times for the time T1. So for one cycle T1 is divided by 18. So the pulse frequency at 4kHz is 12kHz or 1/(T1/18) or simply 3* input frequency I just need the pulse length adjustment and pauses. SO I just use the short time (TS) for my while loop timing for the output signal.
hope this all made sense
Tm=(S1-N1);
T1=(Tm/5)(2PI);
TH=(2/3)PIT1;
TS=TH/30;
I am trying to figure out the context with these timings
is PI = 3.1415926 which is a floating point value which you are using in integer calculation?
does 2*PI refer to one rotation of the engine?
if at 4 KHz T1=15mSec what would you expect TH and TS to be ?
THe out signal is high for 1/30 of 2/3 PI, low for 4/30 then high again for a total of four pulses then a long pause for 14/30
what do you mean by
high again for a total of four pulses is this 4/30?
then a long pause for 14/30 is this low?
I make that a total of 25/30 - what happens in the other 5/30?
Yes, the 2 *PI is in reference to the rotation of the engine. I corrected the int to a float still had the same issues but that is a mistake I should have caught thanks.
Thanks for the code to measure the signal I have been using the oscilloscope I have at work after hours, the code seemed to work fine.
in response to the last question about the expected values TH, TS, and the missing 5/30.
TH would be about twice the value of T1 and then TS would be 1/30th of that, thus the use of 'int' was not all that wise I believe I may still be wrong, I am a mechanical engineer and my coding skills are not the best.
The signal that is returned is high for one time period of TS then low for four times TS. This is repeated four times, this is 20/30 of TH. Then the signal is left low for the remaining of TH or 10/30.
I should mention that I believe I have resolved this issue with the pulseIn() and I will show an update in a few days after I have had a chance to verify with a signal generator and oscilloscope from work.
if T1 is the time for one rotation of the engine (at 4KHz T1 is 15mSec) why do you require PI to calculate the other times - are they not simple divisions of T1? perhaps give some examples of TH and TS
find attached photo of latest experiment
yellow is the 4KHz input signal
green is a trigger for the scope generated every 6 cycles of 1
blue is the latest output signal - there is something wrong with the second pulse it should be identical to the others
find attached photo of latest test
it shows over 6 cycles of 4KHz (yellow trace) three sets of 4 high pulses width 16microseconds (blue trace)
the 4 pulses are arranged as 1 High pulse of 16 microseconds followed by low of 4*16microseconds
this was generated by an arduino mega - I am doubtful about the accuracy using the 16 bit timers of the Mega
I will sort out an arduino Due and try with the 32bit timers
Yes, that is what I was trying to do, I realized at the start of this week that I was making things a bit too complex and started simplifying the calculation. I have been able to do this now using my old code with a few modifications, as well as three other methods. One big mistake I was making is that my values would sometimes become less than one and when that happened the integer became zero. So I was sometimes dividing by Zero or the value was zero so the loop would fail to stop or run in either case.
Using micro() instead of millis() and floats and doubles instead of int where ever I could. This fixed the issues I initially had, also I found a nice function pulseIn() that also simplified the coding a bit and took out the need for the if statement. So I have come up with several methods to code this, thanks for your help and input.
using a Mega I had some problems getting accurate pulse widths therefore I moved over to using an arduino Due which has an 84MHz clock and 32 bit timers
assuming I have your specification correct given a 4KHz signal period .25msec the time for 6 cycles is 1.5mSec gives a TS=15000/90 uSec = 16.67uSec
checking with a scope (see attached photo) the pulse width is 16.8uSec
the Due has a very helpful library which can support such applications