table structure + pwm

Hey there!

I need some quidance with my project. The aim is to read frequency and control solenoid with pwm. Sounds easy, but I need to have map structure like this

50hz ---> 45% pwm
55hz ---> 50%
60 ---> 60%
etc

How can I do this? I think the "if" structure is not the right way. I'am new with arduino.

Maybe the map function?

Yes, that is what I wan't. But I have seen more simple solution somewhere.

bittielmeri:
I need to have map structure like this

50hz ---> 45% pwm
55hz ---> 50%
60 ---> 60%
etc

Was that supposed to be a linear relationship? It isn't.

It is supposed to be nonlinear relationship.

It is supposed to be nonlinear relationship.

Map will only work with a linear relationship and is the simplest thing you can use.
Gor a none linear relationship you have two choices.

  1. express the relationship as an equation.
  2. use a look up table. Either one entry per input / output pair, or if less use linear interpolation to work out the values between table entries.

Grumpy_Mike:

It is supposed to be nonlinear relationship.

Map will only work with a linear relationship and is the simplest thing you can use.
Gor a none linear relationship you have two choices.

  1. express the relationship as an equation.
    2) use a look up table. Either one entry per input / output pair, or if less use linear interpolation to work out the values between table entries.

I think this is what I'am searching for. Have you got any example code or tutorial?

Hi

I just found this topic and it has almost everything I need.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1287600441/0

Here is the code

#include <Flash.h>

const int rpmSteps = 6; // Number of entries for rpm
const long rpmFactor = 1000; // Difference between entries for rpm
const int rpmMin = 2000; // Value of the first entry for rpm
const int rpmMax = rpmMin + (rpmSteps - 1) * rpmFactor; // Value of the last entry for rpm
const int tpsSteps = 7; // Number of entries for tps
const long tpsFactor = 10; //  Difference between entries for tps
const int tpsMin = 0; //  Value of the first entry for tps
const int tpsMax = tpsMin + (tpsSteps - 1) * tpsFactor; // Value of the last entry for tps

FLASH_TABLE(int, font_table, rpmSteps /* width of table */,
    {100,  10,   0,   0,   0,   0},  // 100 %
    {100,  60,  40,  30,  20,  10},  // 90 %
    {100,  80,  70,  50,  30,  30},  // 80 %
    {100,  90,  80,  80,  70,  60},  // 70 %
    {100, 100,  90,  80,  80,  70},  // 60 %
    {100, 100, 100,  90,  80,  80},  // 50 %
    {100, 100, 100, 100, 100, 100}); // 40 %

void setup(void) {
    Serial.begin(115200);
}

void loop() {
  Serial.println (magicnumber(6700, 17));
  Serial.println (magicnumber(3100, 33));
  delay (4000);
}

int magicnumber (int rpm, int tps) {
    int rpmIL, rpmIH;
    int tpsIL, tpsIH;
    long rpmOffset, tpsOffset;

    // Find right table indices to work on
    if (rpm < rpmMin) {
	  rpmIL = rpmIH = 0;
	  rpmOffset = 0;
    }
    else if (rpm > rpmMax) {
	  rpmIL = rpmIH = rpmSteps - 1;
	  rpmOffset = 0;
    }
    else {
	  rpmIL = (rpm - rpmMin) / rpmFactor;
	  rpmIH = rpmIL + 1;
	  rpmOffset = (rpm - rpmMin) % rpmFactor;
    }

    if (tps < tpsMin) {
	  tpsIL = tpsIH = 0;
	  tpsOffset = 0;
    }
    else if (tps > tpsMax) {
	  tpsIL = tpsIH = tpsSteps - 1;
	  tpsOffset = 0;
    }
    else {
	  tpsIL = (tps - tpsMin) / tpsFactor;
	  tpsIH = tpsIL + 1;
	  tpsOffset = (tps - tpsMin) % tpsFactor;
    }

    // Interpolate the values
	long fLL = font_table[tpsIL][rpmIL];
	delayMicroseconds (0);
	long fLH = font_table[tpsIL][rpmIH];
	delayMicroseconds (0);
	long fHL = font_table[tpsIH][rpmIL];
	delayMicroseconds (0);
	long fHH = font_table[tpsIH][rpmIH];

    return (((fLL * (rpmFactor - rpmOffset)
	  + fLH * rpmOffset) * (tpsFactor - tpsOffset))
	  + ((fHL * (rpmFactor - rpmOffset)
	  + fHH * rpmOffset) * tpsOffset))
	  / (rpmFactor * tpsFactor);
}

I'am wondering one thing. The code says that digital pin 7 is input for tps (throttle position sensor, 0-5v output). I would say that we should use analog input because signal is 0-5v. Also I would like to use digital output as PWM output. Now it only prints the value to serial monitor.

To do

  • input pin change
  • pwm output, frequency somewhere between 40-100 Hz
  • table from % to 0-255

EDIT:

-input pin change done

const int tpsSteps = A0;