Help understanding someone elses project code

Hello,

I am trying to build a fuel composition sensor controller. I found a link where someone accomplished this using an uno r3 and a lcd shield link . I have some questions concerning the code that was provided in the original link.

First let me post up the code i have.

/*******************************************************
This program will sample a 50-150hz signal depending on ethanol 
content, and output a 0-5V signal via PWM.
The LCD will display ethanol content, hz input, mv output, fuel temp

Connect PWM output to NEMU Breakoutboard on ADC0-3, and tune
the "FLEX FUEL SETUP" tab accordingly. NOTE: Lowpass filter to
be used on output.

Input pin 8 (PB0) ICP1 on Atmega328
Output pin 3 PWM

If LCD Keypad shield is used, solder jumper from Pin 8 - Pin 2,
and snip leg from pin 8 http://i.imgur.com/KdlLmye.png
********************************************************/

// include the library code:
#include <LiquidCrystal.h> //LCD plugin

// initialize the library with the numbers of the interface pins 
LiquidCrystal lcd(2, 9, 4, 5, 6, 7); //LCD Keypad Shield

int inpPin = 8;     //define input pin to 8
int outPin = 3;    //define PWM output, possible pins with LCD are 3, 10 and 11 (UNO)

//Define global variables
volatile uint16_t revTick;    //Ticks per revolution
uint16_t pwm_output  = 0;     //integer for storing PWM value (0-255 value)
int HZ = 0;                   //unsigned 16bit integer for storing HZ input
int ethanol = 0;              //Store ethanol percentage here

int duty;           //Duty cycle (0.0-100.0)
float period;       //Store period time here (eg.0.0025 s)
float temperature = 0;  //Store fuel temperature here
int fahr = 0;
int cels = 0;
static long highTime = 0;
static long lowTime = 0;
static long tempPulse;

void setupTimer()	 // setup timer1
{           
	TCCR1A = 0;      // normal mode
	TCCR1B = 132;    // (10000100) Falling edge trigger, Timer = CPU Clock/256, noise cancellation on
	TCCR1C = 0;      // normal mode
	TIMSK1 = 33;     // (00100001) Input capture and overflow interupts enabled
	TCNT1 = 0;       // start from 0
}

ISR(TIMER1_CAPT_vect)    // PULSE DETECTED!  (interrupt automatically triggered, not called by main program)
{
	revTick = ICR1;      // save duration of last revolution
	TCNT1 = 0;	     // restart timer for next revolution
}

ISR(TIMER1_OVF_vect)    // counter overflow/timeout
{ revTick = 0; }        // Ticks per second = 0


void setup()
{
  pinMode(inpPin,INPUT);
  setPwmFrequency(outPin,1); //Modify frequency on PWM output
 setupTimer();
   // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Initial screen formatting
  lcd.setCursor(0, 0);
  lcd.print("Ethanol:    %");
  lcd.setCursor(0, 1);
  lcd.print("     Hz       C");
}
 
void loop()
{
  getfueltemp(inpPin); //read fuel temp from input duty cycle
  
  if (revTick > 0) // Avoid dividing by zero, sample in the HZ
		{HZ = 62200 / revTick;}     // 3456000ticks per minute, 57600 per second 
		else                        // 62200 per seconmd seems to be more accurate? 
		{HZ = 0;}                   //needs real sensor test to determine correct tickrate

  //calculate ethanol percentage
		if (HZ > 50) // Avoid dividing by zero
		{ethanol = HZ-50;}
		else
		{ethanol = 0;}

if (ethanol > 99) // Avoid overflow in PWM
{ethanol = 99;}

  //Screen calculations
  pwm_output = 255 * (ethanol*0.01); //calculate output PWM for NEMU
  
  lcd.setCursor(10, 0);
  lcd.print(ethanol);
  
  lcd.setCursor(2, 1);
  lcd.print(HZ);
  
  lcd.setCursor(8, 1); 
  lcd.print(temperature); //Use this for celsius

  //PWM output
  analogWrite(outPin, pwm_output); //write the PWM value to output pin

  delay(100);  //make screen more easily readable by not updating it too often
  
}

void getfueltemp(int inpPin){ //read fuel temp from input duty cycle
highTime = 0;
lowTime = 0;

tempPulse = pulseIn(inpPin,HIGH);
  if(tempPulse>highTime){
  highTime = tempPulse;
  }

tempPulse = pulseIn(inpPin,LOW);
  if(tempPulse>lowTime){
  lowTime = tempPulse;
  }

duty = ((100*(highTime/(double (lowTime+highTime))))); //Calculate duty cycle (integer extra decimal)
float T = (float(1.0/float(HZ)));               //Calculate total period time
float period = float(100-duty)*T;               //Calculate the active period time (100-duty)*T
float temp2 = float(10) * float(period);        //Convert ms to whole number
temperature = ((40.25 * temp2)-81.25); // Calculate temperature for display (1ms = -40, 5ms = 80)
int cels = int(temperature);
cels = cels*0.1;
float fahrtemp = ((temperature*1.8)+32);
fahr = fahrtemp*0.1;

}

void setPwmFrequency(int pin, int divisor) {
  byte mode;
  if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 64: mode = 0x03; break;
      case 256: mode = 0x04; break;
      case 1024: mode = 0x05; break;
      default: return;
    }
    if(pin == 5 || pin == 6) {
      TCCR0B = TCCR0B & 0b11111000 | mode;
    } else {
      TCCR1B = TCCR1B & 0b11111000 | mode;
    }
  } else if(pin == 3 || pin == 11) {
    switch(divisor) {
      case 1: mode = 0x01; break;
      case 8: mode = 0x02; break;
      case 32: mode = 0x03; break;
      case 64: mode = 0x04; break;
      case 128: mode = 0x05; break;
      case 256: mode = 0x06; break;
      case 1024: mode = 0x7; break;
      default: return;
    }
    TCCR2B = TCCR2B & 0b11111000 | mode;
  }
}

After trying this code as it is, my lcd shield wouldnt work. So i found that my DFROBOT shield has a different pinout, so i had to change the code to reflect.

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

Now, here is my question. In the link, above, it says that in order to get this to work you need to add a jumper from pin 8 to pin 2 and cut off pin 8 from the shield. Since my lcd shield has a different pinout how would i go about modifying the rest of the code to use one of the available input and output pins i currently have?

Also, is their a better way to accomplish what is being done in this existing code?

What this is doing is taking a frequency based sensor and converting that into an analog signal output to determine ethanol concentration in gasoline, so it can be used to adjust engine parameters on the fly instead of making educated guesses. It also interprets the duty cycle of the frequency and calculates temperature, and displays both ethenol % and fuel temp on the lcd. Unless im mistaken the arduino is unable to output a analog voltage natively, so i was going to use a DAC (instead of the lowpass filter0 to give the linear 0-5v output needed but am unsure how to modify the code to incorporate this.

Thank you

So i found that my DFROBOT shield has a different pinout

What is it?

As a start, create a table with the original pins in one column and the new pins in the next column. This will give you some idea of what actually needs to change.

Then go through the code and check where the original pins are used and substitute them.

Better yet, define the pins as constants at the top of the file and use the names rather than magic numbers - it will make the code more readable if the pin names are called after what they do.

All of the example code along with the code i originally got had two different versions of this code

// initialize the library with the numbers of the interface pins 
LiquidCrystal lcd(2, 9, 4, 5, 6, 7); //LCD Keypad Shield

Or

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

When i tried to run the code as it was, it wouldnt initialize the screen properly. I went to the DFRobot Wiki and found i needed to change that line of code to this

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

Link

marco_c:
As a start, create a table with the original pins in one column and the new pins in the next column. This will give you some idea of what actually needs to change.

Then go through the code and check where the original pins are used and substitute them.

Better yet, define the pins as constants at the top of the file and use the names rather than magic numbers - it will make the code more readable if the pin names are called after what they do.

I just looked up the pinout for the sainsmart lcd shield that the original author used, and its exactly the same as the DFRobot one i have. Also, when looking closer at his photos, he uses both shields. How his code as posted worked on either is beyond me. I had to change that line of code for the screen to even display at all. I think i might take a stab at writing my own code from scratch. I have zero programming experience, besides making the standard hello world program, but i think i should be able to do this. It shouldnt be a very complicated project as it only needs to accomplish a few things.

  1. take the input frequency and measure the frequency and the duty cycle of the peaks and valleys.

  2. interpret the frequency to an ethenol %, and the duty cycle to a tempurature.

  3. Display both of those values in human readable form on the LCD

  4. Output the ethanol % in a 0-5v linear analog output for interfacing with the engine management system.

The parameters of the sensor are below.

The sensor requires a pull-up to five volts on the signal circuit, and the fuel sensor pulls the 5 volts to ground in pulses. The normal range of operating frequency is between 50 and 150 Hertz:
50 Hertz indicates 0% ethanol, and
150 Hertz indicates 100% ethanol.
The pulse width indicates the fuel temperature. The normal pulse width is between 1 and 5 milliseconds:
1 millisecond indicates -40°C (-40°F), and
5 milliseconds indicates 125°C (257°F).

And don't forget that as you work your own code out you have the reference of the previous code. Someone else's code usually makes more sense as you work it out yourself.