store sensor values into an array

Hi,

I have 2 switches: sw1 and sw2 and a sensor.
I declared my sw1 equal to 0.
Also declared my sw2 to 1.
I want to store the the sensor value on an array whenever any of the switches is pressed.
my array would look like this: [sensor value, sw, sensor value, sw, sensor value, sw ..........]
The "sw" will have a value of "0" when sw1 is pressed and "1" when sw2 is pressed.

Problem is. I know what I want but I don't know how to do the code.
I tried reading some references but I am having a hard time understanding the codes.

urm could you explain it in another way ?

Post the code you have using the proper code tags.

Which bit are you having problems with, reading the switches, reading the sensor or storing the data ?

In pseudo code

declare myArray[]
arrayIndex = 0
loop()
  if sw 1 is pressed
   set myArray[arrayIndex] to 0
   increment arrayIndex
   set myarray[arrayIndex] to sensor value
   increment arrayIndex
  end if
  
  if sw 2 is pressed
   set myArray[arrayIndex] to 1
   increment arrayIndex
   set myarray[arrayIndex] to sensor value
   increment arrayIndex
  end if
end of loop()

How many entries are there likely to be ? Space for the array is not unlimited.
Will the run ever start over again with previous data in the array ? If so think of the implications and be prepared to deal with them.
Putting the data into an array implies that you are going to read it, which you can do in a similar way.
You will lose the data in the array if power goes off. Is that OK ?

Thanks for the replies.
My apology for not posting the requirements clear.

The pseudo code posted by UK HB was I think the same as what I am trying to do.
But one thing is missing. I also want to record what switch was pressed.
From my first post, I assumed sw1 as 0 and sw2 as 1.
So my array would look like [ 500, 0, 600, 1, 300, 1 .....and so on and so forth]
The first element (500) is my sensor value.
The second element (0) denotes that sw1 is pressed.
The third element (600) is also a sensor value.
The fourth element (1) denotes that it is sw2 which is pressed.
I hope I'm being able to explain the requirements clearly now.

For UKHB's reply/questions: I am having problems storing the data as an array.

How many entries are there likely to be ?

The size is not definite but I think it would not exceed 30. Is it ok?

Will the run ever start over again with previous data in the array ?

I don't understand this question sir.

Putting the data into an array implies that you are going to read it, which you can do in a similar way.

I will read it.

You will lose the data in the array if power goes off. Is that OK ?

OOPS! not OK. I have plan B. How about the EEPROM? Can I use it instead of storing my data in an array?

Instead of telling us HOW you think you should solve a problem, tell us WHAT the problem is you are trying to solve.

meowth08:
Thanks for the replies.
My apology for not posting the requirements clear.

The pseudo code posted by UK HB was I think the same as what I am trying to do.
But one thing is missing. I also want to record what switch was pressed.
From my first post, I assumed sw1 as 0 and sw2 as 1.
So my array would look like [ 500, 0, 600, 1, 300, 1 .....and so on and so forth]
The first element (500) is my sensor value.
The second element (0) denotes that sw1 is pressed.
The third element (600) is also a sensor value.
The fourth element (1) denotes that it is sw2 which is pressed.
I hope I'm being able to explain the requirements clearly now.

For UKHB's reply/questions: I am having problems storing the data as an array.

How many entries are there likely to be ?

The size is not definite but I think it would not exceed 30. Is it ok?

Will the run ever start over again with previous data in the array ?

I don't understand this question sir.

Putting the data into an array implies that you are going to read it, which you can do in a similar way.

I will read it.

You will lose the data in the array if power goes off. Is that OK ?

OOPS! not OK. I have plan B. How about the EEPROM? Can I use it instead of storing my data in an array?

My pseudo code stored a value for the switch pressed. 0 for switch 1 and 1 for switch 2. The array holds data for 'number of switch pressed' and 'data read' in alternate bytes. I actually had them the in the opposite order than you asked but that is easy to correct.

"Will the run ever start over again with previous data in the array ?" What I had in mind was that after a run the array will have data in it. If you run the data collection again without clearing the array it will already have data in it. How will you distinguish old data from new when reading it back if there are fewer entries in the second run ? An entry in the array to signify 'end of data' would be advisable. 30 entries, actually 60 because of collecting the switch numbers, will not be a problem unless the data is a huge string of text, which I take it is not the case.

Have you got any code written, even if is not working ? Please post it so that we can help.

Hi,

@PaulS: I believe I have stated the problem on my posts. That is the very reason why UKHB was able to post a pseudo code.

@UKHB: I will make it and post as soon as possible. Additional info: I'm using an arduino with ATMEGA168 microcontroller.

I'm not really sure what your goals are, but this might give you an idea on how to approach EEPROM
you might want to avoid arrays given the EEPROM is writen and read as individual bytes by the standard library included
read up on it a bit first though, EEPROM writes are not unlimited

#include <EEPROM.h>

byte sensorDataAddress=0;
byte switch0Address=1;
byte switch1Address=3;

void setup()
{
  //you need to intilize your sensors here
}

void loop()
{
  if(sensor== expectedReading)
  {
    EEPROM.write(sensorDataAddress, sensordata);
    sensorDataAddress=sensorDataAddress+3
    //there are three readings, so store in every third address spot
  }
  //put the switches in the same way
  if(sensorDataAddress>"3belowYourEEPROMsize" && yourSwitchDataLimitations)
  {
    return;
    //dont write outside the address space of your EEPROM, it will cause issues
  }
}

just something to think about

#include <EEPROM.h>

int sensorVal = 14;
int  footsw = 12;
int  leftsw = 11;
int  rightsw = 10;
int  resetsw = 9;
int  returnsw = 8;
int audio_out = 7;
int addr = 0;
int totalsensorVal;
int lastsensorVal = 0;

void setup()
{
  pinMode(footsw, INPUT);
  pinMode(leftsw, INPUT);
  pinMode(rightsw, INPUT);
  pinMode(returnsw, INPUT);
  pinMode(resetsw, INPUT);
}

void loop()

{
while (digitalRead(footsw) == HIGH)
  {
    sensorVal = analogRead(A0);
    sensorVal = constrain(sensorVal, 330, 470);
    sensorVal = map(sensorVal, 330, 470, 0, 140);
    sensorVal = max(sensorVal, 400);
  }
if (digitalRead(footsw) == LOW)
  {
    totalsensorVal = sensorVal + lastsensorVal;
    lastsensorVal = totalsensorVal;
  }
if (digitalRead(leftsw) == HIGH)                                   //this part
  {
    EEPROM.write(addr, totalsensorVal);
    addr = addr + 1;
    EEPROM.write(addr, 1);
    addr = addr + 1;
    delay (1000);
  }
if (digitalRead(rightsw) == HIGH)
  {
    EEPROM.write(addr, totalsensorVal);
    addr = addr +1;
    EEPROM.write(addr, 2);
    addr = addr +1;
    delay (1000);
  }                                                                         //until this part.
if (digitalRead(resetsw) == HIGH)
  {
    for (addr = 0; addr < 512; addr ++)
     EEPROM.write(addr, 0);
  }
if (digitalRead(returnsw) == HIGH)
  {
    //to be added
  }
}

Please comment.
I tried compiling the code and no errors appeared.

From the code I posted above, I have here several questions.

  1. The "int sensorVal = 14;" designates pin 14 of my arduino to sensorVal. Is that right?
while (digitalRead(footsw) == HIGH)
  {
    sensorVal = analogRead(A0);
    sensorVal = constrain(sensorVal, 330, 470);
    sensorVal = map(sensorVal, 330, 470, 0, 140);
    sensorVal = max(sensorVal, 400);
  }
  1. My aim here is to read the analog voltage while footsw is high.
    My sensor is the y-axis of the accelerometer. It is connected to the thigh of a person such that when the person walks, the y-axis tilts giving several analog output. A footswitch is installed under the shoe such that when the person lifts his foot, the footswitch is at high logic. I used "while" since I want to get the readings when footsw is at logic high. Range of sensorVal is from 330 until 500. From those readings, I want to get the maximum.
    Is my code able to do that?
  2. I have decided to use the EEPROM instead of array. Is the "this part ....until this part" correct?
  1. The "int sensorVal = 14;" designates pin 14 of my arduino to sensorVal. Is that right?
    No. Variable sensorVal is set to 14, but you still need to do
pinMode(sensorVal, INPUT);
and
analog/digitalRead(sensorVal);

to set up the pin and read values from it.

Your method for getting the maximum value is flawed. max(v1,v2) returns the value that is largest. Why 400 in your code ?
You need to do something like

before the loop set a variable, maybe call it maxValue, to zero
start the while loop
  read the sensor
  constrain it if necessary 
  map it to a larger range
  set maxValue to max(maxValue, sensorValue)
end of while loop

maxValue now holds the maximum value read from the sensor

Judging from the names of your variables I assume that there are left and right foot switches. Is that right ?

Hi,

Thanks for the clarification on my question 1.
I'll make necessary changes.

I just learned coding just after buying the arduino board after looking at the example programs last month.
I am not so familiar to pseudo codes but I'm glad I could understand it a bit.

As for getting the max value, I really should map it in a larger range.
I used 400 because I assumed 400 should be the lowest value for my sensorVal. (lowest value for a single step)

The project I am to accomplish is a navigation aid for the blind.
The blind walks with his cane. If he encounters a "decision point", a point where he need to turn left or right, he presses either "leftsw" if he turns left or "rightsw" if he turns right. This is why I have to record the sensorVal. sensorVal is the sensor reading for every step. From my loop, the totalsensorVal is computed and will be recorded to the EEPROM when he presses leftsw or rightsw. Along with this, I also would want to record the switch being pressed. The footsw is to make sure that the blind took a step.

If the blind wants to go back to the original location, he presses returnsw. This part I will take care later. It's accessing the data I saved on the EEPROM.

the blind

please, "the user" is less discriminatory, I know people with walking around with cell phones that are less situationally aware then Helen Keller. Maybe they could use your device too.

your code:
You need to consider how you are going to read back the data and what it needs to look like in order for your "replay" function to parse/understand it. If you write sensor and switch data in sequentially different spots in eeprom this might confuse as to what type of data it is.
Also consider how fast this data can be written because this will affect your length and "resolution" of playback. You will likely get a much finer resolution then you desire. So you will have to make rule about when to sample the data, which you are kinda doing with the switch.

Third and most importantly, this sounds like a run time operation, unless the user needs recount their steps after they have turned off and on the device, you don't need eeprom. In which case its back to storing this in an array. This is better considering your sensor value will be over 400. 400 wont fit in the byte you address in eeprom it can only store up to 255.
I suggest estimating the greatest length of playback(in recording steps) this will help whether you need persistence(eeprom) or not. This way you can pre-define the size of the data structure and be sure the recording fits where you want to put it.

meowth08:
I used 400 because I assumed 400 should be the lowest value for my sensorVal. (lowest value for a single step)

Your code would not work because even if the sensor value was larger than 400. As soon as you work that out the new value is bigger than 400 you read the sensor again, get a new value for the sensor value and overwrite the old one.

When looking for a maximum value having an initial absurdly low value is always a good idea as it will soon be updated.

Did you get your initial question of saving the switch number and a value saved to an array sorted out ?

You need to consider how you are going to read back the data and what it needs to look like in order for your "replay" function to parse/understand it.

This will be my next problem after storing the data.

If you write sensor and switch data in sequentially different spots in eeprom this might confuse as to what type of data it is.

I write "sensor data" first in odd address then the corresponding "switch data" on the next address (even). Data always come in pair and they are stored alternately.

Also consider how fast this data can be written because this will affect your length and "resolution" of playback. You will likely get a much finer resolution then you desire.

How do I do this?

So you will have to make rule about when to sample the data, which you are kinda doing with the switch.

Sensor Data is sampled while "footsw" is at logic high. It stops when "footsw" becomes low. Sensor data is stored in lastsensorVal. The sensor data for the previous step will be added to the next sensor data. The value will continue to add until "leftsw" or "rightsw" is pressed.

You're absolutely right. The totalsensorVal will continue to rise assuming that each step is over 400.

Third and most importantly, this sounds like a run time operation, unless the user needs recount their steps after they have turned off and on the device, you don't need eeprom. In which case its back to storing this in an array. This is better considering your sensor value will be over 400. 400 wont fit in the byte you address in eeprom it can only store up to 255.

Can you help me transform my code so it will be stored on an array instead of the EEPROM? I could not find a good link for me to learn storing data in arrays. It would be better if I learn it too. The arduino examples for array don't help. EEPROM read, write, clear are easier to understand.

I suggest estimating the greatest length of playback(in recording steps) this will help whether you need persistence(eeprom) or not. This way you can pre-define the size of the data structure and be sure the recording fits where you want to put it.

But wait! I think I can do this.

sensorVal = analogRead(A0) / 1000

The value 400/1000 would just be 0.4
But I will have to change my "int" to "float".
Is this a possible solution?

Given the quantity of data you're looking to store and the limitations of the Arduino, if I were you I'd look for a more efficient encoding scheme than recording the direction as a byte/int. I suggest encoding the directin in as few bits as possible (one bit would be enough for left/right) and pack that in a word with the remaining bits used to hold the count. Depending on the resolution you need, you may be able to scale the count as a 7-bit value and store the direction in the eighth bit, enabling you to fit a sample in a byte. If that's too small, the next option is a 16-bit word, but I'd still suggest encoding your sample carefully to make the best use of it - don't go wasting bits by storing a boolean as a byte.

Your code would not work because even if the sensor value was larger than 400. As soon as you work that out the new value is bigger than 400 you read the sensor again, get a new value for the sensor value and overwrite the old one.
When looking for a maximum value having an initial absurdly low value is always a good idea as it will soon be updated.

Let me explain how I understand how to get max value so you could point out where I went wrong.

  1. I read the sensorVal. 2. Constrain it to a range (330 to 470) so any lower readings than 330 will be 330 and larger reading than 470 will be 470.
  2. Map it to a range (which my range for my code is terribly wrong). 4. Compare a value of say "x". Every time it reads a sensor value, it will perform step 2 and 3, then it will compare to "x". Then it will choose which is higher and store it to sensorVal.

Oh yes!!! I got your point now. For the next reading, the sensorVal from the max(sensorVal, 400) will be overwritten.

Did you get your initial question of saving the switch number and a value saved to an array sorted out ?

No sir. I am having difficulty transforming the pseudo code in C.

Given the quantity of data you're looking to store and the limitations of the Arduino, if I were you I'd look for a more efficient encoding scheme than recording the direction as a byte/int. I suggest encoding the directin in as few bits as possible (one bit would be enough for left/right) and pack that in a word with the remaining bits used to hold the count. Depending on the resolution you need, you may be able to scale the count as a 7-bit value and store the direction in the eighth bit, enabling you to fit a sample in a byte. If that's too small, the next option is a 16-bit word, but I'd still suggest encoding your sample carefully to make the best use of it - don't go wasting bits by storing a boolean as a byte.

Thanks for the advice. This is efficient use of memory. I'll try to think of a way to fit my sensor and switch reading into an 8-bit if possible.

The arduino examples for array don't help. EEPROM read, write, clear are easier to understand.

Picture it this way

int addressableDataSpace=150// addressable space within your needs
//something like over 9000! would exceed ram size and crash the program
// thats why you need to keep the size of your data in check
//or look into using an sd card

int mySensorArray[addressableDataSpace]={};
//then to manipulate it
int myNewData=400// something within int value space 
int address=stepSketchIsAt;
mySensorArray[address]= myNewData;
stepSketchIsAt++;
// to read
for (int i=0;i<addressableDataSpace;i++)
{
readBackToUser=mySensorArray[ i ];
}

works similar eeprom except you can define the value include as any data type you want not just a byte.