Pages: 1 2 [3]   Go Down
 Author Topic: Devide 12v square wave signal and output 5v squarewave  (Read 2250 times) 0 Members and 1 Guest are viewing this topic.
Offline
God Member
Karma: 27
Posts: 829
 « Reply #30 on: February 07, 2013, 09:15:54 am » Bigger Smaller Reset

I've just googled optocoupler and it looks that it could be a good idea, I assume these a fast enough?

That depends on the one you select. Most I have looked at would be fast enough. Just translate your PPS to BPS in the datasheets.
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #31 on: February 07, 2013, 09:28:06 am » Bigger Smaller Reset

Pylon, thanks for all your input.

The following formula moves your floats to integers (better uint32_t, precision: 3 digits behind the point):

Code:
square_out = square_in * 201UL / 1138UL ; // case ratio1
square_out = square_in * 420 / 1777; // case ratio2

Where would I add this code, in the main void loop?
so by adding that code, I could set all my variables to integers? What role does the "UL" have?

Is this the correct implimentation?

Code:
/*
Read square wave speed signal in on pin2 and output squarewave speed on pin4
*/

volatile uint32_t lastPulseTime = 0;
volatile uint32_t lastPulseWidth = 0;

const int speed_pin = 2; //sqaure wave input from speed source
const int gear_pin = 3;     //gear select input
const int speed_out = 4; //sqaure wave output

// variables for calculation
const int ratio1 = 1/ 2.315;
const int ratio2 = 1/ 1.731;
const int FD = 1 / 4.7;
const int idler = 1.04;
const int pulses = 4; //pulses per simultated revolution
int square_in; //speed received
int square_out; //speed to send
int gear; // current gear selected
// the setup routine runs once when you press reset:
uint32_t lastEdge = 0;
byte state = 0;

void setup() {
// initialize the digital pin as an output.

pinMode(speed_pin, INPUT);
pinMode(speed_out, OUTPUT);
pinMode(gear_pin, INPUT);

attachInterrupt(0, registerPulse, RISING);
}

// the loop routine runs over and over again forever:
void loop() {
//Sample data to test
square_in = 1000000UL / lastPulseWidth;

/*
read the square wave speed input from "speed_in" into variable "sqaure_in"
*/

gear = digitalRead(gear_pin);
if (gear == HIGH) {        //ratio1 is selected
square_out = square_in / 2 * ratio1 / idler * FD * pulses;
}//end of ratio1

else{        //ratio2 is selected
square_out = square_in / 2 * ratio2 / idler * FD * pulses;
}//end of ratio2

/*
//output the variable "square_out" as square wave to "Speed_out"
*/

uint32_t outPulse = 500000UL / square_out; // get pulse length (not wave length)
uint32_t m = micros();
if (m - lastEdge >= outPulse) {
state = ! state;
digitalWrite(speed_out, state);
lastEdge = m;
}

}
void registerPulse() {
uint32_t cur = micros();
lastPulseWidth = cur - lastPulseTime;
lastPulseTime = cur;
}
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #32 on: February 07, 2013, 11:49:07 am » Bigger Smaller Reset

I have just found out some more info on the sqaurewave speed output from the ECU. The signal is 50% duty so the pulse length is determined by the frequency.The ECU updates the tachometer output every 50mS.

I'm hoping to read the signal in quicker than every 50ms to make sure that I'm not losing data.

I understand that the UNO is 16MHz, but how fast does that mean it could read and ouput data using my code?
 Logged

Switzerland
Offline
Faraday Member
Karma: 108
Posts: 5144
 « Reply #33 on: February 07, 2013, 11:56:10 am » Bigger Smaller Reset

Quote
Where would I add this code, in the main void loop?

That code has to go into your ratio selector if statement like this:

Code:
if (gear == HIGH) {        //ratio1 is selected
square_out = square_in * 201UL / 1138UL;
}//end of ratio1
else{        //ratio2 is selected
square_out = square_in * 420UL / 1777UL;
}//end of ratio2

Quote
so by adding that code, I could set all my variables to integers? What role does the "UL" have?

Yes, you now have to define your variables this way:
Code:
uint32_t square_in = 0;
uint32_t square_out = 0;

The UL hints the compiler that it should recognize the given integer constants as "unsigned long", meaning 32bit positive integers.
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #34 on: February 07, 2013, 12:03:49 pm » Bigger Smaller Reset

Ahh right,

So in this line of code

Code:
square_out = square_in * 201UL / 1138UL;

where did the numbers 201 abd 1138 come from?
 Logged

Switzerland
Offline
Faraday Member
Karma: 108
Posts: 5144
 « Reply #35 on: February 07, 2013, 12:46:09 pm » Bigger Smaller Reset

Your calculation

Code:
square_out = square_in / 2 * ratio1 / idler * FD * pulses;

is the same as (constants replaced)

Code:
square_out = square_in / 2 / 2.315 / 1.04 / 4.7 * 4;

which is the same as (constants pre-calculated)

Code:
square_out = square_in * 0.176745271;

and 201 / 1138 = 0.176625659, which is the same factor with a precision of 3 digits after the point.
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #36 on: February 07, 2013, 01:49:26 pm » Bigger Smaller Reset

Very clever, mathimatically, how did you get to those numbers?

It's not just electronics and c I need to learn
 Logged

Switzerland
Offline
Faraday Member
Karma: 108
Posts: 5144
 « Reply #37 on: February 08, 2013, 05:43:12 am » Bigger Smaller Reset

Quote
how did you get to those numbers?

Take an estimate and approximate till you have the desired precision.
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #38 on: February 08, 2013, 09:00:09 am » Bigger Smaller Reset

very clever
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #39 on: February 08, 2013, 11:37:56 am » Bigger Smaller Reset

I've updated the code:
Code:
/*
Read square wave speed signal in on pin2 and output squarewave speed on pin4
*/

volatile uint32_t lastPulseTime = 0;
volatile uint32_t lastPulseWidth = 0;
uint32_t square_in = 0; //speed received
uint32_t square_out = 0; //speed to send

const int speed_pin = 2; //sqaure wave input from speed source
const int gear_pin = 3;     //gear select input
const int speed_out = 4; //sqaure wave output

// variables for calculation

int gear; // current gear selected
// the setup routine runs once when you press reset:
uint32_t lastEdge = 0;
byte state = 0;

void setup() {
// initialize the digital pin as an output.

pinMode(speed_pin, INPUT);
pinMode(speed_out, OUTPUT);
pinMode(gear_pin, INPUT);

attachInterrupt(0, registerPulse, RISING);
}

// the loop routine runs over and over again forever:
void loop() {
//Sample data to test
square_in = 1000000UL / lastPulseWidth;

/*
read the square wave speed input from "speed_in" into variable "sqaure_in"
*/

gear = digitalRead(gear_pin);
if (gear == HIGH) {        //ratio1 is selected
square_out = square_in * 201UL / 1138UL;
}//end of ratio1

else{        //ratio2 is selected
square_out = square_in * 420UL / 1777UL;
}//end of ratio2

/*
//output the variable "square_out" as square wave to "Speed_out"
*/

uint32_t outPulse = 500000UL / square_out; // get pulse length (not wave length)
uint32_t m = micros();
if (m - lastEdge >= outPulse) {
state = ! state;
digitalWrite(speed_out, state);
lastEdge = m;
}

}
void registerPulse() {
uint32_t cur = micros();
lastPulseWidth = cur - lastPulseTime;
lastPulseTime = cur;
}

Does this look right? is there anything which could be done more affectively?
 Logged

Switzerland
Offline
Faraday Member
Karma: 108
Posts: 5144
 « Reply #40 on: February 08, 2013, 12:00:56 pm » Bigger Smaller Reset

You can eliminate the change from wave length to frequencies and back:

Code:
void loop() {
uint32_t outPulse;

gear = digitalRead(gear_pin);
if (gear == HIGH) {        //ratio1 is selected
outPulse = lastPulseWidth * 1138UL / 201UL;
} else {        //ratio2 is selected
outPulse = lastPulseWidth * 1777UL / 420UL;
}

uint32_t m = micros();
if (m - lastEdge >= outPulse) {
state = ! state;
digitalWrite(speed_out, state);
lastEdge = m;
}
}

The next step is to do the calculation only if one of the input values have changed:

Code:
uint32_t savedPulseWidth = 0;
byte savedGear = LOW;
void loop() {
uint32_t outPulse;

gear = digitalRead(gear_pin);
if (gear != savedGear || lastPulseWidth != savedPulseWidth) {
savedGear = gear;
savedPulseWidth = lastPulseWidth;
if (gear == HIGH) {        //ratio1 is selected
outPulse = lastPulseWidth * 1138UL / 201UL;
} else {        //ratio2 is selected
outPulse = lastPulseWidth * 1777UL / 420UL;
}
}

uint32_t m = micros();
if (m - lastEdge >= outPulse) {
state = ! state;
digitalWrite(speed_out, state);
lastEdge = m;
}
}
 Logged

UK
Offline
Jr. Member
Karma: 0
Posts: 66
 « Reply #41 on: February 12, 2013, 08:18:42 am » Bigger Smaller Reset

Thanks for that, I plan to have my test rig compleated this week to test this on, thanks again for your massive help
 Logged

 Pages: 1 2 [3]   Go Up
Jump to: