Array Search Using Sensor Inputs

Hey guys,

I am working on an assignment for class and i'm a bit stuck. What we are trying to do is take voltage inputs from four separate sensors. We then have a table (converted to an array) that correlates each voltage value to a reading (temperature, barometric pressure ect). Anyways, I was curious how one would search for the correct line in the array, and print the correct column (say column 2 for temperature, column 3 for barometric pressure). I am currently getting an error that says invalid types 'float [33][5] float'. I'm not quite sure what this means. Anyways, i'm not looking for someone to do my homework, just looking for a nudge in the right direction to let me know where I am going wrong. Can't seem to find too much help with the array feature on the arduino website.

float WindSpeed = 1;
float WindDirection = 2;
float Temp = 3;
float BarometricPressure = 4;
float Wind_Speed;
float Wind_Direction;
float Temperature;
float Barometric_Pressure;
float raw_WindSpeed;
float raw_WindDirection;
float raw_Temp;
float raw_BarometricPressure;
float Wind_Speed_array[1][5];
float main_array[33][5] =
{
  {0.000, 0.000, 0.00, 0.0, 950},
  {0.156, 3.125, 11.24, 4.0, 953},
  {0.313, 6.250, 22.50, 8.0, 955},
  {0.469, 9.375, 33.75, 12.0, 959},
  {0.625, 12.500, 45.00, 16.0, 963},
  {0.781, 15.625, 56.25, 20.0, 966},
  {0.938, 18.750, 67.50, 24.0, 969},
  {1.094, 21.875, 78.75, 28.0, 972},
  {1.250, 25.000, 90.00, 32.0, 975},
  {1.406, 28.125, 101.25, 36.0, 978},
  {1.563, 31.250, 112.50, 40.0, 981},
  {1.719, 34.375, 123.75, 44.0, 984},
  {1.875, 37.500, 135.00, 48.0, 989},
  {2.031, 40.625, 146.25, 52.0, 991},
  {2.188, 43.750, 157.50, 56.0, 994},
  {2.344, 46.875, 168.75, 60.0, 997},
  {2.500, 50.000, 180.00, 64.0, 1000},
  {2.656, 53.125, 191.25, 68.0, 1003}, 
  {2.813, 56.250, 202.50, 72.0, 1006},
  {2.969, 59.375, 213.75, 76.0, 1009},
  {3.125, 62.500, 225.00, 80.0, 1013},
  {3.281, 65.625, 236.25, 84.0, 1016},
  {3.438, 68.750, 247.50, 88.0, 1019},
  {3.594, 71.875, 258.75, 92.0, 1022},
  {3.750, 75.000, 270.00, 96.0, 1025},
  {3.906, 78.125, 281.25, 100.0, 1028},
  {4.063, 81.250, 292.50, 104.0, 1031},
  {4.219, 84.375, 303.75, 108.0, 1034},
  {4.375, 87.500, 315.00, 112.0, 1038},
  {4.531, 90.625, 326.25, 116.0, 1041},
  {4.688, 93.750, 337.50, 120.0, 1044},
  {4.844, 96.875, 348.75, 124.0, 1047},
  {5.000, 100.000, 360.00, 128.0, 1050}, 
};
  

void setup()
{
  Serial.begin(9600);
  pinMode(WindSpeed,INPUT);
  pinMode(WindDirection,INPUT);
  pinMode(Temp,INPUT);
  pinMode(BarometricPressure,INPUT);
}

void loop()
{
 raw_WindSpeed = analogRead(WindSpeed);
 raw_WindDirection = analogRead(WindDirection);
 raw_Temp = analogRead(Temp);
 raw_BarometricPressure = analogRead(BarometricPressure);
 Wind_Speed_array = main_array[raw_WindSpeed]; 
 Serial.print(Wind_Speed_array[0][1]);
}

The last two lines are where I am seeing trouble. I basically want to search the main_array for a value that matches raw_WindSpeed (the voltage from that sensor should match the voltage in the first column of the main array), and set that row of values equal to the Wind_Speed_array. Then I want to print the value in column two of that array.

Anyways, like I said, i'm not looking for someone to do the assignment for me. Just looking for a nudge in the right direction. I'm not quite sure how to search the first column of an array and store the entire row into a separate array.

Moderator edit: CODE TAGS. Please read the stick topic at the top of this section.

A couple points that I see right off.

In your setup function you do a bunch of pinMode()s. These are superfluous, and I'm impressed that the serial IO function isn't broken. You don't need to set the analog inputs as INPUT when doing an analog read. And also, what you are actually doing is setting D1-D4 as inputs. (This is what has me impressed with the serial IO function, you are setting the TX output pin (D1) as an input after you initialize the serial port...)

Now, to your direct question. You are trying to compare a reading from an analog pin to a very precise fixed value (three decimal points worth...). There is no guarantee after various resistance, inductance, and capacitance inconsistencies with both the wires and the contacts (not to mention thermal drift of voltage reference generation within the actual ADC of the uP) that you will actually constantly read 0.001V precision. (Well, not quite because of the 10bit resolution, but it's good enough for my point.) What you could do is for each reading step through your array comparing the read value to the stored value. And then take note of the array row that matches. There are two types of comparisons that I can think of right away.

The simplest (but maybe not best) way is to step through and see which is the first line that is greater than the read value, then report the value for the previous line. Unfortunately, this will never use the last line of the array.

A better approach might be (again while stepping through the array) to take the absolute value of the array value minus the read value and store it. In the next and subsequent loops, get the absolute value of the array value minus the read value, store it and compare to the previous absolute value difference. When this difference starts getting larger the closet value is the previous array line (and if you never get the difference to start trending back up the reading is closest to the last value of the array).

I hope that diatribe made enough sense for you to start coding. Your homework now is to decide if my suggestions actually work for you, and then how to code your choice.

Do you really want/need to put the array row whose voltage matches the input into a second array ? Surely you just need the corresponding value from the correct column in a variable then read the next sensor and do the same for the next voltage reading until you have done all 4, then you can print the variables,

Good luck with the assignment

The line in your code "Wind_Speed_array = main_array[raw_WindSpeed];" seems to me to be trying to index into an array using a floating point number (the raw windspeed) as the index.

I am surprised that floating point numbers can index an array. However even if they can there is a world of difference between picking out a row in an array with an index number (e.g. 5 for row 5 etc) and finding a row that has a value in a particular cell.

I think you need a loop that iterates through each row of the main array and which stops when it finds one with the correct windspeed. And picking up the point made by SEMBAZURU you will probably need to check for values that are greater than or less than your detected value because finding an exact match would be very unlikely.

...R

float WindSpeed = 1;
float WindDirection = 2;
float Temp = 3;
float BarometricPressure = 4;
...
float raw_WindSpeed;
float raw_WindDirection;
float raw_Temp;
float raw_BarometricPressure;
...
void setup()
{
  Serial.begin(9600);
  pinMode(WindSpeed,INPUT);
  pinMode(WindDirection,INPUT);
  pinMode(Temp,INPUT);
  pinMode(BarometricPressure,INPUT);
...
void loop()
{
 raw_WindSpeed = analogRead(WindSpeed);
 raw_WindDirection = analogRead(WindDirection);
 raw_Temp = analogRead(Temp);
 raw_BarometricPressure = analogRead(BarometricPressure)

It's difficult to imagine so many wrong things in such a small amount of code.

Pin numbers should normally be constant, and certainly of an integer datatype, preferably "byte".
They're used as analogue inputs, so the pinMode is irrelevant.
analogRead returns an integer, not a float.

You don't need to set the analog inputs as INPUT when doing an analog read.

And, in fact, you can't set the mode of the analog pins. They are INPUT only.

PaulS:

You don't need to set the analog inputs as INPUT when doing an analog read.

And, in fact, you can't set the mode of the analog pins. They are INPUT only.

Depending on the uP on the Arduino, yes and no. On my UNOr3 I can use my analog pins as digital I/O using pinMode, digitalRead, and digitalWrite. I haven't yet tried to confuse my poor little ATmega328 by trying to get an ADC value off of a digital I/O pin... I'm not sure about the other uPs on various different Arduinos and clones though, I'd double check the schematic for the Arduino and the datasheet for the uP before trying though. The OP never mentions which Arduino model he/she (I'm not sure of the gender from the handle, and no gender is set in the user profile) is trying to use.

On my UNOr3 I can use my analog pins as digital I/O using pinMode, digitalRead, and digitalWrite.

And you can set the mode of the digital pin. But, you can not set the mode of the analog pin. That is hardwired to INPUT.

PaulS:

On my UNOr3 I can use my analog pins as digital I/O using pinMode, digitalRead, and digitalWrite.

And you can set the mode of the digital pin. But, you can not set the mode of the analog pin. That is hardwired to INPUT.

Heh... I think we have a context/semantic issue here. I was saying that I can use the pin that is labeled A0 on my UNOr3 board as D14. It is the same physical connection on the Arduino, thus the same pin on the ATmega328. Yes, the ArduinoIDE references them differently making it appear as separate pins, but depending on the target uP A0 and D14 may or may not be the same physical pin. I think my words for what you were saying would be "... you can set the mode of the digital use of a pin. But you can not set the mode of the analog use of an ADC pin." Do you find that a reasonable re-statement of your statement?

The OP seemed to mistakenly think they needed to set a pin as an input whether or not it was analog or digital. (And then set digital 1-4 as inputs instead of the intended, but incorrect, analog 1-4.) A common mistake for a beginner. I suspect they have learned the error of their ways by this point in the thread. :wink:

Do you find that a reasonable re-statement of your statement?

Yes.

I suspect they have learned the error of their ways by this point in the thread.

Hope strings eternal.

AWOL:

<SNIP>

analogRead returns an integer, not a float.

@AWOL
Good catch on the analogRead(), I had forgotten (brain-fart on my part) about that.

@Kpellu2
The analogRead() returns an integer in the range of 0-1023 on the default 10bit ADC mode. (You don't mention which Arduino you are using, so we don't know if there is a 12bit ADC mode for the analog pins you are using, but as I remember Arduinos default to 10bit even if 12bit is there. This is important because the range of 12bit ADCs is 0-4095.) Your code would need to translate the ADC count value to a voltage level with some simple proportional arithmetic.