Jump to content

HELP WITH ELECTRONIC PROBLEM


attleej

Recommended Posts

Dear All,

I am experiencing problems with writing a sketch (program) for an Arduino.  I am desperate for some expert help.  If anyone can help or pass my problem on to someone who can, it would be much appreciated.  The description of the problem below gets more and more technical!

SITUATION

The Meteor M120 tank engine is nearing completion and we have at least one MkIVB engine that will be completed at some point and all will require testing on a run-up rig.  The M120 because I need to map the fuelling and the MkIVB because it is a lot of work to fit one and only then to find that it does not run properly or has a problem.  There will als be plenty of other IVBs tat would require testing, no doubt.  The M120 is quicker to fit but the same arguments apply.

RUN-UP RIG CONCEPT

The run up rig will be designed to accept a Meteor engine on its coolant rails.  Unfortunately a IVB is a bit different from an M120 but this can be accommodated.  To apply a load I intend to use a "Telma" retarder which should absorb about 500 BHP.  This should be able to absorb the load for some time.  In order to test for full power I am minded to fit either another "Telma" or fit a truck disc brake unit.  Conceivably, I might just use disc brake units but obviously they would quickly overheat.  The cooling system will consist of two Antar radiators and fan units that are in stock.

The problem with a Heenan and Froud water dynanometer is that the hot water still has to be cooled unless there is a large tank of water available.  Since I would like the rig to be very mobile, this is not desirable. 

OUTPUT TORQUE MEASUREMENT

I intend to measure the output torque by means of strain gauges on the propellor shaft between the engine and the "Telma" and brake units. It would be possible to mount the Telma on a truck hub and then  measure the reaction to hold it still.  Unfortunately this will not work if I wanted to add disc brake units for full power testing.  The strain gauges and its amplifier will be mounted on the prop shaft and rotating.  The challenge is to transmit a signal from the rotating prop shaft to the electronics  and the display unit. Obviously, the mounting will have to be balanced.  This will probably be achieved by duplicating everything so that it is largely symetrical. .  The signal will be transmitted via an infrared system

ELECTRONIC CONCEPT

The output voltage of the Strain Gauge Amplifier (SGA) will vary in direct proportion to the torque being transmitted by the prop shaft. The analogue to digital converter on the 'rotating' Arduino Uno will convert the voltage from the SGA to a value between 0 and 1023.  Since the maximum torque will never exceed 2000 ft lbs this should give enough definition.  I have drafted a sketch (program) for the Arduino which is designed to send a series of pulses at 38 KHz.  The length of the pulse, or rather the burst, will be in proportion to the output from the SGA and thus the torque being transmitted. The pulse length is currently designed to be between 0 and 1023 milliseconds but of course this can easily be altered, if required. The output of the 'rotating' Arduino Uno goes, via a resistor to the IR LED.

The IR signal is received by the decoder,  Vishay type TSSP 4038.  It is only sensitive to IR signals at 38 KHz and gives a LOW output when receiving a signal. This output goes to the fixed Arduino Uno. and the pulse length is measured.  The sketch on the Fixed Arduino includes the servo library and the mapping function has been used to drive the servo.  The servo will be connected to a needle which will indicate on a scale the torque being transmitted. This is all quite straight forward.  The torque figure can also be combined with the RPM to give a BHP output.  This can be displayed by another servo meter.

THE PROBLEM

The problem is that I cannot reliable measure the length of the pulse from the IR decoder.  I have tried two techniques.  Firstly,  "pulsein" and secondly using using "millis".  The sketches are below..  If I cannot do this, I cannot transmit the torque signal from the rotating prop shaft to the fixed equipment either by IR or other means. This problem manifests itself in that the serial print value will not change as expected nor will the servo move as expected.

WHAT DOES WORK

The varying voltage from the SGA is being simulated by the a Pot supplied with 5V from the Arduino.  The osciloscope, (Scope) shows that the voltage from the pot rises and falls smoothly and this is reflected in the P/O value of between 0 and 1023 from the serial printer.

The 'fixed' Ardunio is receiving the signal from the IR decoder and can make an LED pin on A2 light when the decoder is active and sending a LOW signal.  (The decoder pulls the relevant pin , A1,  HIGH when inactive.)  The IR link can be demonstrated with no difficulty in an ON / OFF mode.

The scope shows the LOW output from the IR decoder rising and falling in line with the signal going to the 'rotating' IR LED. with the same start and end point.

When the servo "sweep" example is loaded as a sketch, the servo moves as expected.

When the output from the 'rotating' Arduino feeding the IR LED is 'hard wire'  connected to the 'fixed' Arduino, the scope shows the pulse length varying as expected but the the problem of measuring the pulse length continues.

CONCLUSION

The above describes the problem as best I can.  The sketches below show what I have tried.  It would be so helpful if someone could tell me where I am going wrong!  I would be very happy to discuss it further on the phone.

Many thanks,

John

 

THE SKETCHES

The 'rotating' Arduino

//  INTRODUCTION

//The purpose of this Sketch is to generate a 38 KHz burst with a burst length in proportion to the PotValue.  
//IDC the PotValue will be replaced by a voltage from the strain gauge amplifier mounted on a rotating propellor shaft.
//The 38 Khz signal will be discriminated by the IR receiver at the Rx end.

const int PotVoltPin = A0;                     //Voltage from potentiometer used to determine pulse length. 
const int SigOutPin = A2;                       //Pin for Output pulse to pin 4 for the IR sender. 
const int SigInPin = A1;                       //Connected to "Sig In switch" microswitch.  Used to test system.
int SigInState = 0;                            //Pin for input from "Sig In Switch" which is a microswitch on Tx board.
int PotValue = 0;                              //A value between 0 and 1023 in proportion to the voltage on the PotVoltPin
unsigned long AdjVal = 1;                      //A value that can be used to adjust length of pulse to ensure that it is long enough to be accurate.
unsigned long Duration = 0;                    //The desired duration of the pulse after being modulated by the AdjValue.

void setup() 
{
pinMode(PotVoltPin,INPUT);                     //Sets the PotVoltPin as an input
pinMode(SigOutPin, OUTPUT);                    //Sets this OutPin as an output.
pinMode(SigInPin,INPUT);                       //Sets this as input, is connected to microswitch.
Serial.begin(9600);                            
}

void loop() 
{
SigInState = digitalRead (SigInPin);            //Test to see if "Sig In switch" microswitch is pressed in order to perform test
PotValue = analogRead(PotVoltPin);              //Read the PotVoltPin to give PotValue which will be between o and 1023
Duration = (PotValue * AdjVal);                 //Calculates desired duration of burst from PotValue and AdjV
if (SigInState == HIGH)
  {
  tone(SigOutPin, 38000, Duration);
  SigInState = digitalRead (SigInPin); 
  Serial.println(Duration);
  }
  else
  {
  noTone; 
  }
delay (100);
}
 

 The 'fixed Arduino and using millis.

/*  INTRODUCTION

The purpose of the strain gauge receiver (SGR) is to receive the pulse transmitted by the strain gauge transmitter (SGT)and re-package it as a value in proportion to the strain and hence torque being measured.  
It does this by measuring the length of the pulse coming from the transmitter. 

The signal from the transmitter is received by an IR decoder that recognises the 38 KHz bursts.  NOTE WELL!!!!  The IR decoder sends the input pin LOW when active.. 
In this sketch what is really a "burst" is called a "pulse" because the output from te IR decoder is a contiuous LOW wen active.

The external LED illuninates whenever a burst is being received. It is fed wia a 390 ohm resistor to limit the current.  It is fed wia a 390 ohm resistor to limit the current.

POWER SUPPLY

The receiever needs 12 volts that comes in via a 3 way military screwed connector.

TESTING
The sketch works when the input pulse is from one to ten seconds long.  It does not work when the pulse length is miliseconds but it is not understod why.
WIRING CODES

Red           = 12 volt supply.  
Black         = Ground and 12 Volt neg.
Yellow        = Output pulse from Arduino generated in proportion to voltage from the potentiometer.
Pink          = 5 volts from Arduino to supply the potentiometer.
Orange        = output from potentiometer varying between 0 and 5 volts.
Grey / green  = injection pulse generated by Speeduino.
White         = SErvo and LCD
ARDUINIO CONNECTIONS AND FUNCTIONS

Red           To Vin
Black         To GND
Yellow        To A2
Pink          To 5V
Grey / green  To A1  (Set as OUTPUT)
White         To A0 (Servo)
*/
#include <Servo.h>
Servo myservo;                                   // create servo object to control a servo
//#include <LiquidCrystal.h>                     // initialize the library by associating any needed LCD interface pin

//const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;    // with the arduino pin number it is connected to
//LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int SigInPin = A1;                         //Decoded signal from the IR receiever.
const int LedPin = A2;                           //Tell tale LED
int SigInState = 0;                             
int OldSigInState =0;
unsigned long val = 0;
unsigned long Duration = 0;                      //The length of the burst recieved.
unsigned long NewMillis =0;
unsigned long OldMilis = 0; 

void setup() 
{
pinMode(SigInPin,INPUT);                        //Sets the SigInPin as an input
pinMode(LedPin,OUTPUT);                         //Set LedPin as output.
myservo.attach(A0);                             // attaches the servo on pin 9 to the servo object
//lcd.begin(16, 2);                             // set up the LCD's number of columns and rows:
Serial.begin(9600);                            
}

void loop() 
{
SigInState = digitalRead (SigInPin);            //Reads SigInPin to check state.
if
(SigInState != HIGH)                            //If SigInState is not HIGH
      {
      digitalWrite ( LedPin,HIGH);              //Tell tale LED is turned on.
      }
else
      {
      digitalWrite ( LedPin,LOW);               //If SigInPin is HIGH, (ie no pulse) LED is turned off. 
      }
if
(SigInState ==LOW && OldSigInState ==HIGH)      //Test if new pulse has come in
     {
     (NewMillis = millis() );                   //NewMillis to equal current millis.
     (OldSigInState = SigInState );             //OldSigState is reset.
     }
 if
(SigInState ==HIGH && OldSigInState == LOW)     //Tests if pulse has ended
     {
     (Duration = millis() -NewMillis);          //Calculates duration as diff bewteen millis and new mills
     OldSigInState = SigInState;                //resets OldSigInState.
     }                  
val = map(Duration, 0, 1023,180,0);             // scale it to use it with the servo (value between 0 and 180)
myservo.write(val);                             // sets the servo position according to the scaled value
delay (15);
Serial.println ( Duration );                  //Prints to serial printer to see what is going on.
}

Finally, the 'fixed' Arduino using the pulsein function.
 

/*  INTRODUCTION

The purpose of the strain gauge receiver (SGR) is to receive the pulse transmitted by the strain gauge transmitter (SGT)and re-package it as a value in proportio to the strain and hence torque being measured.  
It does this by measuring te length of the pulse coming from the transmitter. 

The signal from the transmitter is received by an IR decoder that recognises the 38 KHz bursts.  The IR decoder sends the input pin LOW. In this sketch what is really a "burst" is called a "pulse" because the output from te IR decoder is a contiuous LOW wen active.


The external LED illuninates whenever a burst is being received. It is fed wia a 390 ohm resistor to limit the current.  It is fed wia a 390 ohm resistor to limit the current.

POWER SUPPLY

The receiever needs 12 volts that comes in via a 3 way military screwed connector.

TESTING
The sketch works when the input pulse is from one to ten seconds long.  It does not work when the pulse length is miliseconds but it is not understod why.
WIRING CODES

Red           = 12 volt supply.  
Black         = Ground and 12 Volt neg.
Yellow        = Output pulse from Arduino generated in proportion to voltage from the potentiometer.
Pink          = 5 volts from Arduino to supply the potentiometer.
Orange        = output from potentiometer varying between 0 and 5 volts.
Grey / green  = injection pulse generated by Speeduino.
White         = SErvo and LCD
ARDUINIO CONNECTIONS AND FUNCTIONS

Red           To Vin
Black         To GND
Yellow        To A2
Pink          To 5V
Grey / green  To A1  (Set as OUTPUT)
White         To A0 (Servo)
*/
#include <Servo.h>                               //Inserts servo library.
Servo myservo;                                   // Create servo object to control a servo
//#include <LiquidCrystal.h>                     // Initialize the library by associating any needed LCD interface pin

//const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;    // with the arduino pin number it is connected to
//LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int SigInPin = A1;                         //Decoded signal from the IR receiever.
const int LedPin = A2;
int SigInState = 0;
unsigned long val = 0;
unsigned long Duration = 0;                      //The length of the burst recieved.

void setup() 
{
pinMode(SigInPin,INPUT);                         //Sets the SigInPin as an input
pinMode(LedPin,OUTPUT);                          //Sets LedPin as an output
myservo.attach(A0);                              //Attaches the servo on pin A0 to the servo object
//lcd.begin(16, 2);                              //Set up the LCD's number of columns and rows:
Serial.begin(9600);                            
}

void loop() 
{
noInterrupts(); 
Duration = pulseIn(SigInPin,HIGH);              //Measures te pulselength in microseconds. should be between 0 and 1023 milliseconds
interrupts();
Duration = (Duration /1000);                    //Converts microseconds into milliseconds.  Expected pulse length is between 0 and 1023 milliseconds.
val = map(Duration, 0, 1023,180,0);             //Scale it to use it with the servo (value between 0 and 180)
myservo.write(val);                             //Sets the servo position according to the scaled value
delay (15);                                      //Delay to allow the servo to move.
Serial.println ( Duration );   
}


 

Link to comment
Share on other sites

I know nothing about Arduinos, but a little about programming logic, so I'll offer a solution, with apologies in advance if I've misread the logic.

I think the problem is in 

if
(SigInState ==LOW && OldSigInState ==HIGH)      //Test if new pulse has come in                                               {called TEST 1}
     {
     (NewMillis = millis() );                   //NewMillis to equal current millis.
     (OldSigInState = SigInState );             //OldSigState is reset.
     }
 if
(SigInState ==HIGH && OldSigInState == LOW)     //Tests if pulse has ended                                                          {called TEST 2}

I assume that the loop in which these tests are written executes multiple times for each burst, with TEST 1 and TEST 2 being evaluated on each execution. If so, NewMillis is reset each time the loop executes [as TEST 1 will always succeed until the end of the burst] and will always end with the same value. I would suggest that you need a flag of some sort, set to 0, and a further test nested within TEST 1 which tests the flag and only executes the two statements if the flag = 0, and then sets flag = 1. This will stop NewMillis being updated thereafter. A statement will then be needed within TEST 2 setting the flag back to 0.

Link to comment
Share on other sites

Dear Noel7,

 

It is so helpful to have a little help to bounce ideas and test my logic.  There is an Arduino forum but they are not very tolerant of thickos like me, they all seem to act as if they are Phd students!

I should explain that millis is an Arduino timer that increments by one, every millisecond. It overflows 49 days after being booted up!

TEST 1 only runs once when the SigInState goes LOW.  I thought I had got the 'flag' with OldSigInState. TEST 1 has two tests to be met.  The first is that the SigInState is LOW, ie active.  The second is that the OldSigInState is HIGH. The first time TEST 1 is TRUE, OldSigInState is changed to LOW.  Thus TEST 1 can only be TRUE the first time that it runs.

TEST 2  should only run once for similar reasons.

When I changed the sketches so that a ten second pulse was needed to move the servo 180 degrees, it worked fine.  I could move the needle to wherever I wanted to (more or less) just by pressing a switch and giving it a pulse of the right number of seconds.

I hope that you can tell me what error I have made!  If you cannot help me, I will have to go into the Lion's den that is the Arduino Forum.

 

John

 

 

 

Link to comment
Share on other sites

Dear All,

 

I think that I have worked out where I am going wrong.  Please don't waste any more time on this.

For the curious: I have mapped the pot on the 'rotating' side and sent an IR signal between 0 and 1023 ms.  I should have mapped the pot value to get a pulse length of between 0 and 2.25 ms.. 

I will get there!

 

John 

Link to comment
Share on other sites

I know zilch about Arduinos and my limited programming experience is now very rusty.

However 30 ish years ago I took a different approach. The voltage output of the SGA was the input to a voltage to frequency converter. The range I recall was around 3 - 8 kHz. This was then transmitted via a radio transmitter - receiver pair on ( I think ) 418MHz. The receiver was connected to a frequency to voltage converter then displayed on a volt meter. Now with a suitable interface the frequency could be displayed and recorded with a computer.

Link to comment
Share on other sites

David,

Thank you for this.

I think that I have cured the problem.  I did not take into account that Serial.Print and digitalWrite are slow functions that get in the way of measuring a pulse that might only be a few milliseconds long.  (When I used pulses of a few seconds, it worked perfectly.)  I now have it so that the LCD display on the 'transmitter' development board shows the same value as the receiver's LCD and the needle on the servo for the prototype gauge moves in sympathy with the pot on the transmitter development board.

The rest of it should be fairly straightforward and well within my humble capability.

John

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...