Sensor

Hello,

I am trying to get a peak value from a set of data .
I tried by comparing each data point with the one before it and the one after it and if it is greater , then an action (soleniod-open/close)is supposed to be performed.

But the code writes data to the sd card for a couple of seconds and stops. The solenoid which is supposed to open/close at a apeak value abruptly opens or closes.

Can anyone please find the mistake and help me correct it.

Thank you

If you have an array of values like in your case senval[3] and you want to find the peak value in that array, you simply step through the array:

int currentPeak = 0 ;  // global
. . . 
. . . 
for ( int i = 0; i <3; i++ ) {
   if ( senval[i] > currentPeak ) currentPeak = senval[i] ;
}

At the end, currentPeak holds the maximum value found in the array senval

if (senval[0]>>senval[1])

is a bitshift. I think you were looking for greater than. That's just >.

    if (senval[0] >> senval[1])
  if (senval[1] >> senval[0] && senval[1] >> senval[2])

Whoops !

Another oopsie.

if(count=0)

Another oopsie.

Code: [Select]
if(count=0)

Corrected it.

But no change. The solenoid abruptly switches on/off and the sd card also stops and starts writing with some seconds gap.

Print the values in senval before finding the "peak". Print the value defined as the "peak". Are the values what you expect?

How is the solenoid powered/isolated from the Arduino?

Print the values in senval before finding the "peak".

I printed the values of the array in serial print and they came out correctly.

Print the value defined as the "peak". Are the values what you expect?

I did not try printing the peak value. I will try it. Thank you for the suggestion.

How is the solenoid powered/isolated from the Arduino?

I am using promini at 3.3V and a solenoid which needs 5V to open/close.
For, now I am using a bench top power supply set at 5 V which connects to the raw pin of the arduino and the sensor and other parts are powered by Vin pin from the arduino. (The sensor and other parts require 3.3V)
The solenoid is powered from the same power supply (so that it gets 5V) and is connected to pin 4 of the arduino.

So, when the power-hungry solenoid fires up, all kinds of havoc is wreaked on the Arduino. Hmmm. You need diodes to keep out back-EMF and capacitors to moderate the current spiking.

So, when the power-hungry solenoid fires up, all kinds of havoc is wreaked on the Arduino. Hmmm. You need diodes to keep out back-EMF and capacitors to moderate the current spiking.

I used the solenoid with a code which tested change in pressure with the previous value and it worked pretty fine. (like exactly how it was supposed to. open when pressure high, close if not).

I attached a picture of the circuit which came with the solenoid.
Please have a look at it and suggest if I still need the capacitors and diodes.
The solenoid wires go to the green one. The (1) + is connected to power supply, (2)- to ground and gate(3) to arduino pin 4.

solenoid circuit.PNG

solenoid circuit2.PNG

Apart from all the typing errors, you also appear never set the value of pressure in the loop() so it will have the value zero and pressure determines pressure_mmhg, the parameter of which you are trying to determine the peak value.

It appears you are attempting, on every loop iteration, to:
(a) read a pressure sensor (although the code is missing)
(b) determine if the value just read is the highest this session and if so switch the solenoid on, otherwise switch it off.
(c) write an entry to a log file.

If so, your first problem is the cycle speed of the loop which could mean your solenoid is on for say say 100 microseconds and the SD card will soon fill up. I guess at least you need some sort of timing element to ensure this loop activity only happens periodically say every 2 seconds.

On a quick analysis of the new code you appear to have added, you still need some form of limit in the loop otherwise things are going to go wrong like the integer count will overflow and the SD card will fill up.

How often do you want to sample temperature and pressure ? Every 20mS ? (you now have a 20mS delay in the loop). That still appears to be very short intervals between samples and count may overflow after about 20 minutes.

Also your logic for determining the peak value of pressure_mmhg seams rather complicated if you are interested in its peak value in the session (since the Aduino is switched on)

Why not simply do something like this:

//logic for finding peak and controlling the solenoid:

  static int peak_pressure_mmhg;  
  if ( pressure_mmhg > peak_pressure_mmhg ) {
     peak_pressure_mmhg = pressure_mmhg ;
     digitalWrite(4, HIGH);
     delay(1000);//logic
  }
  else {
    digitalWrite(4, LOW); //logic
  }

But anyway, you have made big changes since you first published your code. What are the outstanding problems (if any) ?

Here is an example of executing everything in the loop at a specific time interval, in this case 2000mS but you can configure the value as required:

void loop()
{
  static unsigned long lastIterationMs ;
  if ( millis() - lastIterationMs > 2000UL  )  {   
   lastIterationMs = millis() ;

   // 
   //  here you put all the code you currently have in loop()
   //  and it will be executed every 2000mS.
   //  if you want another interval, change the if statement above.
   // 

  }
}

Try with a such a long interval, then reduce it if you need more samples per second.

How will the controller know if the value is the peak pressure?

the peak pressure is defined as the highest value of pressure_mmhg seen so far in this session and is stored in the variable peak_pressure_mmhg. If a higher value pressure is later seen, then peak_pressure_mmhg is updated accordingly.

The problem remains the same. The solenoid opens and closes very abruptly without any coherence with the logic written for it to open/close. Also, the data is written to the sd card, stops abruptly for few millisec and then starts recording the data again( in the same file.) The readings are with 65ms gap with this code.

(a) temporarily replace the solenoid and driver circuit with a led and current limiting resistor (say 330 Ohm) to see if the problem goes away.

(b) your logic for changing the SD filename is difficult to follow and I wonder how the compiler has interpreted it. Can you give a few examples of the filenames you would like to see ?

The solenoid opens and closes very abruptly without any coherence with the logic written for it to open/close.

If you have you confirmed that the solenoid is triggered by the peak value, but is not staying open for one second then I think you have a power problem causing it to drop out.

I used the solenoid with a code which tested change in pressure with the previous value and it worked pretty fine. (like exactly how it was supposed to. open when pressure high, close if not).

Did you do this with the SD card writing? The SD write can take 200 ma. and the fact that you see some drop out in SD records may also indicate a power issue.

Rather than dealing with the count variable, and the overflow issues, I would just make sure that you take three readings and fill the array, before testing for a senval[1] which is greater than senval[0] and senval[2].

but when I give delay(1000) after the solenoid opens, the sd card stops writing data. after the delay, it starts writing again.

That's not the only thing that stops. That's why we suggest that you never use delay(). Read, understand, and embrace the blink without delay example's philosophy.

While it specifically relates to blinking an LED, what it teaches is how to do something at a known time after doing something else, without blocking.

I figured out the problem.

Are you going to let us know what you found?

How do I keep the solenoid in open/close position for 1-5 sec once it is open/close without letting the sd card stop writing data?

Get rid of the delay(). When the solenoid opens, save a startTime = millis(), and set a flag = true. Then you can use a "blink without delay" style timer like this in loop.

if(flag==true && millis() - startTime>=interval)
{ //close solenoid
//write the flag false
}

When the solenoid opens, save a startTime = millis(), and set a flag = true.

But, do NOT call it flag. Give it a meaningful name.

 else
    {
      if (solstate == true && millis() - startTime >= interval)
        digitalWrite(4, LOW);
      solstate = false; //logic

    }

It certainly looks like you are missing a bracket for multiple actions within the millis() timer if statment. You don't want to turn the condition false until it is met.

 else
    {
      if (solstate == true && millis() - startTime >= interval)
         {
            digitalWrite(4, LOW);
            solstate = false; //logic
          }

    }

What I'm unclear about is if you want the solenoid to retrigger and what is physically possible in your system. For example, you see the max value and you trigger the solenoid. A second and a half later you see another trigger condition from your three values, the solenoid will retrigger for another two seconds before it has timed out from the first peak. Is that what you want?

Please post complete code. Add some serial debugging statements to see what your values are at every step.

and for limits 0 to -500 am getting the same values (0 and -500 being printed in serial monitor).

You set them back to those values right before you print them.

senval[0] = senval[1];
    senval[1] = senval[2];
    senval[2] = 0;
    Pmin = 1;
    Ppeak = -500;

For FLT_Max and FLT_Min i am getting Ppeak and Pmin values as ovf

I don't see in the code were these values are declared.

    Pdelta = Ppeak - Pmin;
    if ( Pdelta >= 20)
    {
      digitalWrite(4, HIGH);
      startTime = millis();
      solstate = true; 
    }
    else
    {
      if (solstate == true && millis() - startTime >= interval)
      {
        digitalWrite(4, LOW);
        solstate = false; 
        
      }
    }

Does this code trigger the solenoid in a more predictable manner than the previous code which did not look at the delta?
I thought that the problem in the previous code was the retriggering of the solenoid for an indeterminent period of time, rather than a fixed period.

What are you actually trying to achieve with the activation of the solenoid. I thought you the previous code was triggering at the correct point. Does it only want to be triggered once? What is the solenoid connected to?

Perhaps I missed it, but can you explain to me what your system is doing physically with the pressure and the solenoid and what you are trying to achieve. I've been pretty focused on some of the small details, and I'm not sure I have the big picture.