PDA

View Full Version : PWM/code limit? analog instruments cessna 206



Jahanzeb
12-10-2013, 04:11 PM
so after successfully controlling a meter with link2fs, with the help of Jim and a few other members, i quickly rushed to build my own instruments. i dont know how to scale images to fit the meter, so i had to resort to very crude methods, and actually draw the tachometer on a piece of paper, to scale. it didnt come out too bad, surprisingly. (picture attached) anyway, i got it working and had my very first instrument working, perfectly synced with fsx and correctly calibrated. excited, i quckily went out and bought a few meters. After a few runs to the market, i found an even cheaper alternative. AC voltmeters used in household UPS. they cost me 30 cents a piece. i opened them up, bypassed the massive resistor, and had full deflection from the arduino's 5.5V 40ua. my excitement grew, and i spent a the weekend making fuel guages. (again, by hand, sadly) plugged in the meters, and now i had two fuel guages, all calibrated and good to go.

My next aim was oil temp and oil pressure guages. following the same procedure, i made the guages. added a few lines to the code. the code, did become quite lengthy at this point, running 5 instruments. it lost its efficiency. i figured that, thats because it has to read all those line to reach the end of the loop, to go back to the begining of the loop, and thus loses time to make the needles move smoothly. it reads a value say 1500RPM. as i increase RPM, the needle stays there for a good second, although my actual RPM is now 2500 since it takes time to reach the end of the loop. when it startes the loop again, it reads the new value, "2500" and moves the needle directly to 2500. at least thats what i think is happening.

I was fine with the jerky movements, but then i decided to add the MAP instrument. (manifold pessure) the meter fails to respond completely. it responds sometimes, spurradically, but doesnt move from that value. i checked the code many times. seems to be fine. i copied the code which drives the MAP seperately onto a new sketch, and it works flawlessly. i even tried changing it to fuel flow. the same problem arises.

is it possible that i cant drive more PWM with this code? i have 14 PWMs. only used 6.

I know that the code has become very crude and inefficient because of the size and logic. i'd be grateful if someone could help me out. am i on the right track at least?



int j1;
String leftfuel;
int j2;
String eng1rpm;
int j4;
String Rightfuel;
int j5;
String oiltemp;
int j6;
String oilpress;
int j3;
String MAP;


void setup() {
pinMode(2,OUTPUT);
digitalWrite(2, LOW);
pinMode(3,OUTPUT);
digitalWrite(3,LOW);
pinMode(8, OUTPUT);
digitalWrite(8, LOW);
pinMode(9, OUTPUT);
digitalWrite(9, LOW);
pinMode(10,OUTPUT);
digitalWrite(10,LOW);
pinMode(11,OUTPUT);
digitalWrite(11,LOW);
Serial.begin(115200);
Serial.flush();
}

void loop() {
if (Serial.available() > 0)
{
j1 = Serial.read();
if (j1 == '>')
j1 = Serial.read();
if (j1 == 'a')
{
delay (11);
leftfuel = "";
leftfuel += char(Serial.read());
leftfuel += char(Serial.read());
leftfuel += char(Serial.read());
leftfuel += char(Serial.read());
int leftfuelInt = leftfuel.toInt();
leftfuelInt = map(leftfuelInt, 0, 0045, 0 ,50);
analogWrite(8,leftfuelInt);
}
}
if (Serial.available() > 0) {
j4 = Serial.read();
if (j4 == '>')
j4 = Serial.read();
if (j4 == 'c')

{
delay (11);
Rightfuel = "";
Rightfuel += char(Serial.read());
Rightfuel += char(Serial.read());
Rightfuel += char(Serial.read());
Rightfuel += char(Serial.read());
int RightfuelInt = Rightfuel.toInt();
RightfuelInt = map(RightfuelInt, 0, 0045, 0 ,50);
analogWrite(9,RightfuelInt);
}
}
if (Serial.available() > 0) {
j2 = Serial.read();
if (j2 == 'O'){
delay (11);
eng1rpm = "";
eng1rpm += char(Serial.read());
eng1rpm += char(Serial.read());
eng1rpm += char(Serial.read());
eng1rpm += char(Serial.read());
int eng1rpmInt = eng1rpm.toInt();
eng1rpmInt = map(eng1rpmInt, 0, 260, 0 ,135);
analogWrite(10,eng1rpmInt);
}
}
if (Serial.available() > 0) {
j5 = Serial.read();
if (j5 == '=')
j5 = Serial.read();
if (j5 == 'I')

{
delay (11);
oiltemp = "";
oiltemp += char(Serial.read());
oiltemp += char(Serial.read());
oiltemp += char(Serial.read());
oiltemp += char(Serial.read());
int oiltempInt = oiltemp.toInt();
oiltempInt = map(oiltempInt, 120, 0, 0 ,60);
analogWrite(2,oiltempInt);

}
}
if (Serial.available() > 0) {
j6 = Serial.read();
if (j6 == '=')
j6 = Serial.read();
if (j6 == 'E')

{
delay (11);
oilpress = "";
oilpress += char(Serial.read());
oilpress += char(Serial.read());
oilpress += char(Serial.read());

int oilpressInt = oilpress.toInt();
oilpressInt = map(oilpressInt, 0, 115, 0 ,50);
analogWrite(3,oilpressInt);

}
}
if (Serial.available() > 0) {
j3 = Serial.read();
if (j3 == '=')
j3 = Serial.read();
if (j3 == 'P')

{
delay (11);
MAP = "";
MAP += char(Serial.read());
MAP += char(Serial.read());
int MAPInt = MAP.toInt();
MAPInt = map(MAPInt, 0, 40, 0 , 100);
analogWrite(11,MAPInt);
}
}
}




84128413

JMeller
12-10-2013, 06:20 PM
Hello.
I can understand the reason there is such a lag! As the arduino runs down your code, it is stealing information from the serial buffer. By luck or chance it reads the correct combination to make the instruments work. :) That's ok, because here is the reason:
1.) At the top of the void loop, you need to read one character from the serial buffer. This character will be an identifier such as "=", "<", etc.
2.) After obtaining the identifier, it now needs to read one more character- the alphabet character to know what instrument.
3.) Read a determined amount of characters (set by L2FS) to determine the value of the instrument. It's common for people to read too many characters or not enough characters in this area; thus, it messes up streaming information down the line.

Correct setup:



void loop() {
if (Serial.available() > 0)
{
j1 = Serial.read(); // see step 1
if (j1 == '>') {

j1 = Serial.read(); // see step 2
if (j1 == 'a')
{
delay (11);
leftfuel = "";
leftfuel += char(Serial.read()); // see step 3
leftfuel += char(Serial.read()); // see step 3
leftfuel += char(Serial.read()); // see step 3
leftfuel += char(Serial.read()); // see step 3
int leftfuelInt = leftfuel.toInt();
leftfuelInt = map(leftfuelInt, 0, 0045, 0 ,50);
analogWrite(8,leftfuelInt);
} // end of 'a'

if (j1 == 'c')

{
delay (11);
Rightfuel = "";
Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3
int RightfuelInt = Rightfuel.toInt();
RightfuelInt = map(RightfuelInt, 0, 0045, 0 ,50);
analogWrite(9,RightfuelInt);
} // end of 'c'

} // end of '>'




if (j1 == '='){ // see step 2

j1 = Serial.read();
if (j1 == 'I')

{
delay (11);
oiltemp = "";
oiltemp += char(Serial.read());// see step 3
oiltemp += char(Serial.read());// see step 3
oiltemp += char(Serial.read());// see step 3
oiltemp += char(Serial.read()); // see step 3
int oiltempInt = oiltemp.toInt();
oiltempInt = map(oiltempInt, 120, 0, 0 ,60);
analogWrite(2,oiltempInt);

} //end of 'I'
if (j1 == 'E')

{
delay (11);
oilpress = "";
oilpress += char(Serial.read());// see step 3
oilpress += char(Serial.read());// see step 3
oilpress += char(Serial.read());// see step 3

int oilpressInt = oilpress.toInt();
oilpressInt = map(oilpressInt, 0, 115, 0 ,50);
analogWrite(3,oilpressInt);

} // end of 'E'

} // end of '='
} // end of serial >0

}// end void loop

So, if you look at your previous code, you'll notice it was told read from the serial buffer, not because an identifier told it to but, because of the statement " if (Serial.available() > 0)". The serial read directly after that statement was stealing characters from you.

I hope I was able to shed light on the 'why' the code was lagging and not performing to expectations.

Jahanzeb
12-11-2013, 05:16 AM
oh man! you just made my day. thanks for going through the code and actually explaining what i was doing wrong. i understand what you said completely. didnt know i was completely off. thanks for your help and what you offer to the communiy. ive been following you around on the forums and you've done some awesome work.

re-wrote the whole sketch with the help of what you said above and the example. everything is working perfectly. the lag is comepletely gone. when i monitor the serial, the values change at an astonishing rate and thus no lag.

one question though. link2fs reads fuel tank as "0045" (for full fuel). so when i reduce character reads to 2, it doesnt work. thats what i mapped

RightfuelInt = map(RightfuelInt, 0, 0045, 0 ,50);
and made it read four serial reads. i cant do
RightfuelInt = map(RightfuelInt, 0, 45, 0 ,50); with two serial reads. am i doing it wrong?
Thanks,
Regards

JMeller
12-12-2013, 12:21 AM
It's great you eliminated the lag. As for your latest question, I cannot answer it since I haven't evolved to mapping. I'm hoping someone will jump on this thread and point you in the right direction.

Perhaps it's time for me to evolve? :)
Cheers!

BuzziBi
12-12-2013, 04:31 AM
Hi Jahanzeb (http://www.mycockpit.org/forums/member.php?u=22554) .
I also have made som analog instruments, and as you, I got problems!
I tryied the code for all of my instruments separatly, and they works fine. But putting things together, not so much.
I could run (a bit unsure) 5 meters without error, but adding more, gave me problems.
My solution was to run four Edgwice Meter's on a Mega card, and four Edgwice Meter's on a Uno card. 8 in total.
I whispered to Jim that there could be a limitation in Link2fs, but he says that there should be no problems running 8 on a card ........ so?
Maybe we should sponsor James, so he can buy some Edgwice Meters, and give us the solution :p

Here is the thread where I discussed this with Jim.
http://www.mycockpit.org/forums/showthread.php?t=26752&highlight=instruments

Jim NZ
12-12-2013, 11:28 PM
I'll have an experiment on this one in the next few days and report.
I can't see any reason that all the PWM pins can't be used at once ,, but maybe I'm wrong ,,, I do remember, back in 1954 when ,,,,

:) Jim

Jahanzeb
12-13-2013, 03:56 AM
Buzz,
ive been on that thread, stalking you guys. you did manage to get 8 PWMs to work at the same time right? my code was wrong, so i figured that maybe i couldnt connect more, cuz of that. with Jmeller's help, im gonna try 8 PWM on the mega and see what happens. your cockpit is coming along nicely. exactly the kind i want. taken your advice, and actually learned photoshop basics and the instruments are coming along nicely. calibrating them, is a whole new story. today, im going to be playing with servos. read some interesting stuff on this forum, esp the one that Jim recently posted.
Jim, looking forward to your results.
cheers

JMeller
12-13-2013, 06:06 PM
J,
I had re-read your question about the mapping. It had more to to do with string operators than mapping. What you need to do, as you already know, is discard the two characters if they are "0". This can be done a multitude of ways, but below is an easy to follow (untested) example:

if (j1 == 'c')

{
delay (11);
Rightfuel = "";
Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3

if (Rightfuel == "00"){Rightfuel = "";} // erase the two characters


Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3
int RightfuelInt = Rightfuel.toInt();
RightfuelInt = map(RightfuelInt, 0, 45, 0 ,50);
analogWrite(9,RightfuelInt);
} // end of 'c'

Jim NZ
12-14-2013, 02:54 AM
Re the PWM pins ,,,

I had all the PWM's on a Mega going all at once ,, they all went fine.
Thats 12 PWM's (pins 2 to 13)
What I done was use LED's and a mixture of inputs to brighten or darken the LED's.

Here's a typical grab ,,,,

case 'G'://Found the second identifier "flaps"
flaps = "";
flaps += getChar();
flaps += getChar();
flaps += getChar();
flapsINT = flaps.toInt(); // convert it to an integer (Thanks Phill)
flapsINT = constrain(flapsINT, 0, 50);//limits any reading to between 0 and 50)
flapsINT = map(flapsINT, 0, 50, 0 ,255);
analogWrite(12,flapsINT);
break;

With the above I read the flaps on the baron in FSX ,, maximum expected figure is 57.
For a 'play' I limited the input to 50 using 'constrain' and it works fine.
If I had not used 'Constrain' ,,, then when the flaps position hit 51 (or higher) the 'map' function would crash and the output could be anything.
I think this may be the area that is causing you Guys trouble (out of range mapping) ???
In proper coding both those "50"s would have been 57. (Maximum expected figure)
I would think it's good insurance to use 'constrain' prior to any mapping.

Now also ,,,,
Watch out if you are also using the servo library ,, it can disable some PWM pins ,,, see,,,
http://arduino.cc/en/Reference/Servo

PWM pins are only on certain pins on Arduino's ,, it's normally written on the card.

Check out "Constrain ,,,,
http://arduino.cc/en/Reference/Constrain

Check out "Map" ,,,,
http://arduino.cc/en/Reference/Map

All in all ,,, It went fine ,,, Jim.

p.s. re this 0045 thing ,,, I would have thought that once the string "0045" gets converted to an integer it would be 45 ???

BuzziBi
12-14-2013, 05:03 AM
I did a Google on adding zeros to int, and thats a long canvas!
As You say Jim, also explained her, that "045", "0045","00045" = "45" in a integer. So Why do we have to take them into consideration?
http://social.msdn.microsoft.com/Forums/vstudio/en-US/dad3330a-0d8d-4815-bbc3-b6f05d6b8b05/how-to-add-zero-to-an-integer-value-from-left-like-999-to-0999 (http://social.msdn.microsoft.com/Forums/vstudio/en-US/dad3330a-0d8d-4815-bbc3-b6f05d6b8b05/how-to-add-zero-to-an-integer-value-from-left-like-999-to-0999)
Is it that we in the code asks the card to expect a certain amount of figures, then as we send zeros, get a result out of range?
Then James: " if (Rightfuel == "00"){Rightfuel = "";} // erase the two characters"
would be the best solution. Just ignore the first expected figures.

Jahanzeb
12-14-2013, 05:21 AM
James,

J,
I had re-read your question about the mapping. It had more to to do with string operators than mapping. What you need to do, as you already know, is discard the two characters if they are "0". This can be done a multitude of ways, but below is an easy to follow (untested) example:

if (j1 == 'c')

{
delay (11);
Rightfuel = "";
Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3

if (Rightfuel == "00"){Rightfuel = "";} // erase the two characters


Rightfuel += char(Serial.read()); // see step 3
Rightfuel += char(Serial.read()); // see step 3
int RightfuelInt = Rightfuel.toInt();
RightfuelInt = map(RightfuelInt, 0, 45, 0 ,50);
analogWrite(9,RightfuelInt);
} // end of 'c'


thats an interesting line. setting the first two "00" to null. of course the code works fine. but after playing with the code, you cant eliminate the next two serial reads as you still need to read the next two digits. (just like you've done) so i need 4 serial reads to read a value "0045".

further, i tested the code by doing 4 seial reads and writing the code as
RightfuelInt = map(RightfuelInt, 0, 45, 0 ,50);
without the line
if (Rightfuel == "00"){Rightfuel = "";}
the result is the same. but if i use 2 serial reads, with the value from fsx of 0045.. then that doesnt work.

so basically, if im getting a 4 digit reading from fsx, i need to do 4 serial reads. the point of the line
if (Rightfuel == "00"){Rightfuel = "";} // erase the two characters
loses its meaning. since i can get the same result by doing 2 more reads. 0045, does not get converted to 45 when converted to integer. if it did, 2 serial reads would've been sufficient?
i could be wrong, being a newbie. correct me if im wrong

Jim NZ
12-15-2013, 12:30 AM
Jahanzeb, I re-read everything in this thread in case I was not understanding something but the answer is staring you right in the face ,, have a read of my post (post #9) and understand what is happening.
In that posted routine it reads 3 "serial.reads" and only uses 2.
There is a reason why the extra digits are there but the fact is ,, that's how many digits you have to read.

I had 12 similar routines running and all worked as it should ,, this was to help you and Buzzi ,,, but you just chose to ignore it.

In your last post you say 0045 does not convert to an integer of 45 ,, wrong ,,, but just in case there was something really weird in the Arduino coding I tried a bit of code and a string "0045" does end up being 45 when converted to an integer.

My suggestions ,,,
Be sure of your facts before posting them.
Use the "multi" instead of the "inOut".
Study the demo's.
Play and fiddle so you get to understand what is happening.
Do your own research and fiddling before asking for help.
Then ,, if in trouble ,, ask.

Of course at the end of the day you can use anything you like and code how-ever you like but please don't mess other Guys around that are trying to help you.

Jahanzeb
12-15-2013, 02:50 AM
Jim.thanks for going through the trouble and out of your way to help.
I did post after fiddling around a lot, but couldn't understand it. I wasn't trying to mess anyone up. I stated that I'm a newbie and I was trying to understand what was happening in the code. I wasn't challenging anyone or saying anyone's wrong. If I did mess anyone up, I'm sorry.. Il do more research before posting.
Thanks for your help guys.
appreciate it