Help on retrieving values from matrix

Hello, I’m kinda new to programming in Arduino.
I was trying to simulate a VE map on arduino. So I’d need to analog inputs (in an ecu it’d be RPM and kPA) I’m using 2 potentiometers. And as an output i’d need to retrieve values from a matrix.
So for a given X value and a given Y value, i need a given value on that matrix. I was using pin 7 as power for the potentiometers. In the far-ish future, i want to build my own engine and wanted to program the ecu. I don’t think I’ll be using arduino, i’d need mulitple things happening at the same time, but still, i wanted to try arduino out.
This is the simulation code i came up with.
But nothing happens when i turn the potentiometers and the led doesnt light up.
some help please?

int ledred= 9;
int rpot= A0;
int lpot= A1;
int rval;
int lval;

void setup() {
pinMode (ledred, OUTPUT);
pinMode (rpot, INPUT);
pinMode (lpot, INPUT);
pinMode (7, OUTPUT);

}

void loop() {

digitalWrite (7, HIGH);
int VE[rval][lval] = {
{20,20,20,23,26,31,32,35,39,40},
{25,25,25,29,32,38,47,50,54,59},
{30,30,30,33,45,50,55,59,62,65},
{33,33,35,37,49,56,58,69,72,75},
{40,40,41,45,53,59,60,77,79,80},
{44,44,45,53,59,61,62,77,79,83},
{45,45,47,55,62,64,65,77,79,83},
{48,48,50,56,68,68,69,77,79,83},
{49,49,51,60,67,70,70,77,79,83},
{49,49,51,60,67,70,70,77,79,83},
{49,49,51,60,67,70,70,77,79,83},
{49,49,51,60,67,70,70,77,79,83},
{49,49,51,60,67,70,70,77,79,83},
};

int rval = analogRead (rpot);
rval = map(rval, 1, 1024, 0, 9);
int lval = analogRead (lpot);
lval = map(lval, 1, 1024, 0, 12);
int FVE;
FVE = map(VE, 0, 99, 1, 255);
analogWrite (ledred, FVE);

}

FVE = map(VE, 0, 99, 1, 255);

While VE is a map for an engine, it is not going to use the Arduino map() function.

Try...

FVE = VE[lval][rval];

But you must make sure those lval and rval values are valid array addresses. map() will quite happily return values off the ends of the scale. Use constrain().

I know map wont give me a map ahaha, Thanks for the suggeston, but wouldn't doing so just give me the values in the matrix? while i do want to retrieve them, i would like the value to be transformed into something usefull, hence why i mapped it. So the

FVE = map(VE, 0, 99, 1, 255)

was trying to map the matrix values to pwm output values. with the maximum being 255 ie the led is lit.
I apologize if I'm not being clear, or if you answered and i didn't understand.

FVE = map(VE, 0, 99, 1, 255);

In that line of code, VE does not represent the value from the matrix, but a pointer to the memory address where the matrix is stored. To get the value from the matrix, based on the values of lval and rval, you need to use the code posted by MorganS in the map() function:

FVE = map(VE[lval][rval], 0, 99, 1, 255);

A few additional points, analogRead() returns a value from 0 through 1023, not 1 through 1024, and since your matrix appears to be limited to values from 0 through 99, it can be defined as a byte array instead of an int array and would only take half as much memory to store.

Why not put the PWM values in the array ?

For a 3-dimensional lookup (input is (x,y), output is z) you want to do a bi-linear interpolation in both directions to smooth the output.

In the example below, I use indexes that range from 0x00 to 0x8f (columns) and 0x00 to 0xbf (rows). The indices can be considered as 4.4 fixed-point values, where the upper nibble is the “integral” value (so 0x0 to 0x8 for cols, 0x0 to 0xb for rows) that is used to index into the table.

The lower nibble forms the fractional part used for the interpolation.

As a 2D example, suppose you had a single-row table such as:

   //col #         0x  1x  2x  3x  4x  5x  6x  7x  8x  9x  Ax  Bx  Cx
const byte tbl[] =  0,  5,  10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60
________________________________________________|    |
|                                                    |
35                                              40----
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
y0 y1 y2 y3 y4 y5 y6 y7 y8 y9 yA yB yC yD yE yF
                              ^^
Let idx = 0x7A -----------------
Index = 0x7 (0x7A >> 4)
Frac = 0xA  (0x7A & 0x0f)
tbl[Index] = 35
tbl[Index+1] = 40
value = 35 + (40-35) * Frac/16
value = 35 + 5 * 10/16
value = 35 + 3.125
value = 38 (fractional part of fraction ignored)

In the 3D example, you just add additional stages of interpolation for the added dimension.

re the fraction, you can include it if you like, by checking the result of (p11 - p01)*fraccol (e.g.); if bit 3 is set (so the lower nibble is >= 0x80), you can round up the high-nibble if it’s <0xf_. Requires a bit more work but adds accuracy…)

This example using your table doesn’t include the fractional round-up but it can be added if you want:

const byte rpot= A0;
const byte lpot= A1;
const byte ledred = 9;

byte VE[][10] = 
{   //                 col
    //0x  1x  2x  3x  4x  5x  6x  7x  8x  90
    { 20, 20, 20, 23, 26, 31, 32, 35, 39, 40 }, // 0x
    { 25, 25, 25, 29, 32, 38, 47, 50, 54, 59 }, // 1x
    { 30, 30, 30, 33, 45, 50, 55, 59, 62, 65 }, // 2x
    { 33, 33, 35, 37, 49, 56, 58, 69, 72, 75 }, // 3x
    { 40, 40, 41, 45, 53, 59, 60, 77, 79, 80 }, // 4x
    { 44, 44, 45, 53, 59, 61, 62, 77, 79, 83 }, // 5x
    { 45, 45, 47, 55, 62, 64, 65, 77, 79, 83 }, // 6x   row
    { 48, 48, 50, 56, 68, 68, 69, 77, 79, 83 }, // 7x
    { 49, 49, 51, 60, 67, 70, 70, 77, 79, 83 }, // 8x
    { 49, 49, 51, 60, 67, 70, 70, 77, 79, 83 }, // 9x
    { 49, 49, 51, 60, 67, 70, 70, 77, 79, 83 }, // Ax
    { 49, 49, 51, 60, 67, 70, 70, 77, 79, 83 }, // Bx
    { 49, 49, 51, 60, 67, 70, 70, 77, 79, 83 }  // C0
    
};

void setup() 
{
    Serial.begin( 9600 );

    pinMode( rpot, INPUT );
    pinMode( lpot, INPUT );
    pinMode( ledred, OUTPUT );
    
}//setup

void loop() 
{
#if 1    
    for( byte row=0; row<0xc0; row++ )
    {
        for( byte col=0; col<0x90; col++ )
        {
            byte val = map( bilinearInterpolate( row, col ), 0, 83, 0, 255 );
            Serial.println( val );
            analogWrite( ledred, val );
            
        }//for
            
    }//for
#else
    int rval = map( analogRead( rpot ), 0, 1024, 0, 0xbf ); //rows from 0x00 to 0xbf
    int lval = map( analogRead( lpot ), 1, 1024, 0, 0x8f ); //cols from 0x00 to 0x8f
    //
    int FVE = map( bilinearInterpolate( rval, lval ), 0, 0x83, 0, 0xff );
    
    analogWrite( ledred, FVE );
    
    delay(10);
#endif
    
}//loop

byte bilinearInterpolate( byte rowval, byte colval )
{
    byte
        idxrow, idxcol,
        fracrow, fraccol,
        p0, p1, pval,
        p01, p11,
        p00, p10;

    //ensure table limits are not exceeded
    if( rowval > 0xbf )
        rowval = 0xbf;
    if( colval > 0x8f )
        colval = 0x8f;

    //upper nibbles are indexes into the rows/cols
    //lower nibbles allow 15-steps of interpolation in x and y directions 
    idxrow = rowval >> 4;
    fracrow = rowval & 0xf;
    //
    idxcol = colval >> 4;
    fraccol = colval & 0xf;

    //get the four "corner" values from the table at (row, col) and (row+1, col+1)
    p01 = VE[idxrow][idxcol];
    p11 = VE[idxrow][idxcol+1];
    p00 = VE[idxrow+1][idxcol];
    p10 = VE[idxrow+1][idxcol+1];

    //perform bilinear interpolation (integer math) within that square
    p1 = p01 + (((p11 - p01)*fraccol)>>4);
    p0 = p00 + (((p10 - p00)*fraccol)>>4);
    pval = p1 + (((p0-p1)*fracrow)>>4);

    //return 3rd dimension (Z value) from bilinear interp
    return pval;
    
}//bilinearInterpolate

Note the “#if 1” in loop() allows checking the PWM with a scope and loops for testing. If you want to try the potentiometers, change the ‘1’ to ‘0’.

P.S. Not a mathematician so I probably messed something up. It seems to work on the scope. YMMV.

P.P.S. This example only works for positive right/down tables. If you need to, check for negative slopes and apply the appropriate changes as needed…

Sorry If I didn’t replay in these days, college got to me lol. When I’ll get a free moment I’ll get to it, Thank you all for the help.
ps, what is 0x00, 0x8f, 0xbf?

tonysancruzz:
Sorry If I didn't replay in these days, college got to me lol. When I'll get a free moment I'll get to it, Thank you all for the help.
ps, what is 0x00, 0x8f, 0xbf?

Hexadecimal representations of zero (0x00) and of the max table elements; the high nibble (so '8' or 'b') is the maximum whole row or column and the low nibble ('f') represents the "fractional" part, allowing 16 levels of interpolations between adjacent row or column entries.