Hi guys,
I am doing a project in which I am collecting data from a sensor. I need to set a threshold and run a vibrator if the data is below it. The thing is that the vibrator should turn on for 2 seconds and turn off for 5 mins even if the data is below threshold. I cannot use delay because I want the data to be displayed in serial monitor at all times.
Do you have a working code?
I think vibration for 2 seconds for every 5 min is like a heartbeat and can be accomplished via millis().
Below example can be used for that purpose tweak it for your needs. Blink rate should be 300000 for 5 minutes intervals.
Please take time and learn Blink Without Delay concept
// Define these at the top of your sketch.
#define LEDBLINK_PIN 13 // I/O pin connected to the LED.
#define LEDBLINK_MS 1000 // Blink rate (in milliseconds).
void setup()
{
// For ledBlink(), set LEDBLINK_PIN to output.
pinMode(LEDBLINK_PIN, OUTPUT);
}
void loop()
{
// Blink the LED to let the user know we are still alive.
ledBlink();
// Do something.
}
//
// LED Heartbeat routine by Allen C. Huffman (www.appleause.com)
//
void ledBlink()
{
static unsigned int ledStatus = LOW; // Last set LED mode.
static unsigned long ledBlinkTime = 0; // LED blink time.
// LED blinking heartbeat. Yes, we are alive.
// For explanation, see:
// http://playground.arduino.cc/Code/TimingRollover
if ( (long)(millis()-ledBlinkTime) >= 0 )
{
// Toggle LED.
ledStatus = (ledStatus==HIGH ? LOW : HIGH);
// Set LED pin status.
digitalWrite(LEDBLINK_PIN, ledStatus);
// Reset "next time to toggle" time.
ledBlinkTime = millis()+LEDBLINK_MS;
}
} // End of ledBlink()
Have a look at how millis() is used to manage timing without blocking in several things at a time
...R
@omersiar, got there just before me
I have checked out the millis() tutorial. I dont think you got me.
My code's serial output is heartrate values which come out every second. I need to code so that a vibrator goes off for 2 seconds if the heart rate is below 90 and turn it off for 5 minutes even if the incoming heart rates are below 90.
My code to display heart rate is:
#include <SoftwareSerial.h>
SoftwareSerial nss(8,5); // Put your TX and RX pins here, in the correct order, nss represent heartRate
byte vals[3];
const int numReadings = 10;
int heartRate, oxyLevel;
int readings[numReadings];
int readIndex = 0; // the index of the current reading
float total = 0; // the running total
float average = 0; // the average
void setup()
{
nss.begin(9600); // Or whatever is appropriate
Serial.begin(9600);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}
void loop()
{
if(nss.available() >= 3)
{
vals[0] = nss.read(); //represent byte 1
vals[1] = nss.read(); //represent byte 2
vals[2] = nss.read(); //represent byte 3
heartRate = 0; // Sets all 8 bits to 0
oxyLevel = 0; // Sets all 8 bits to 0
bitWrite(heartRate, 0, bitRead(vals[1], 0)); // Set bit 0
bitWrite(heartRate, 1, bitRead(vals[1], 1)); // Set bit 1
bitWrite(heartRate, 2, bitRead(vals[1], 2)); // Set bit 2
bitWrite(heartRate, 3, bitRead(vals[1], 3)); // Set bit 3
bitWrite(heartRate, 4, bitRead(vals[1], 4)); // Set bit 4
bitWrite(heartRate, 5, bitRead(vals[1], 5)); // Set bit 5
bitWrite(heartRate, 6, bitRead(vals[1], 6)); // Set bit 6
bitWrite(heartRate, 7, bitRead(vals[0], 0)); // Set bit 7
bitWrite(heartRate, 8, bitRead(vals[0], 1)); // Set bit 8
oxyLevel = vals[2];
}
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = heartRate;
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits
Serial.print("Heart rate: ");
Serial.println(heartRate);
Serial.print("avg: ");
Serial.println(average);
delay(1); // delay in between reads for stability
}
If you now edit your post and use square brackets instead of < and > for the code tags you will have it right
fame3096:
I have checked out the millis() tutorial. I dont think you got me.
My code's serial output is heartrate values which come out every second. I need to code so that a vibrator goes off for 2 seconds if the heart rate is below 90 and turn it off for 5 minutes even if the incoming heart rates are below 90.
I think it is you who have not understood the relevance of using millis() as in the example. Try again.
...R
hey guys, Sorry for asking too much. I did take time to study millis(). I wrote up a code and the led turns on for 2 seconds when the average HR is < 95 and then turns off for 5 seconds but then the data is not displayed in the serial monitor during this 2 seconds on time and 5 seconds off time.
#include <SoftwareSerial.h>
SoftwareSerial nss(8,5); // Put your TX and RX pins here, in the correct order, nss represent heartRate
byte vals[3];
const int numReadings = 10;
int heartRate, oxyLevel;
int readings[numReadings];
int readIndex = 0; // the index of the current reading
float total = 0; // the running total
float average = 0; // the average
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change :
const long ontime = 2000; // interval at which to blink (milliseconds)
const long offtime = 5000;
void setup()
{
nss.begin(9600); // Or whatever is appropriate
Serial.begin(9600);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
pinMode(13,OUTPUT);
}
void loop()
{
if(nss.available() >= 3)
{
vals[0] = nss.read(); //represent byte 1
vals[1] = nss.read(); //represent byte 2
vals[2] = nss.read(); //represent byte 3
heartRate = 0; // Sets all 8 bits to 0
oxyLevel = 0; // Sets all 8 bits to 0
bitWrite(heartRate, 0, bitRead(vals[1], 0)); // Set bit 0
bitWrite(heartRate, 1, bitRead(vals[1], 1)); // Set bit 1
bitWrite(heartRate, 2, bitRead(vals[1], 2)); // Set bit 2
bitWrite(heartRate, 3, bitRead(vals[1], 3)); // Set bit 3
bitWrite(heartRate, 4, bitRead(vals[1], 4)); // Set bit 4
bitWrite(heartRate, 5, bitRead(vals[1], 5)); // Set bit 5
bitWrite(heartRate, 6, bitRead(vals[1], 6)); // Set bit 6
bitWrite(heartRate, 7, bitRead(vals[0], 0)); // Set bit 7
bitWrite(heartRate, 8, bitRead(vals[0], 1)); // Set bit 8
oxyLevel = vals[2];
}
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = heartRate;
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits
Serial.print("Heart rate: ");
Serial.println(heartRate);
Serial.print("avg: ");
Serial.println(average);
delay(1); // delay in between reads for stability
unsigned long onTime = millis();
if(average>95){
while(millis() - onTime < 2000){
digitalWrite(13,HIGH);
}
while(millis() - onTime < 5000){
digitalWrite(13,LOW);
}
}
else{
digitalWrite(13,LOW);
}
}
Now, this works just like a delay. If I copy paste the first 2/3rd of the code(data output) right after the 2 second on time and 5 second off time, It works like I need it to.
if(nss.available() >= 3)
{
vals[0] = nss.read(); //represent byte 1
vals[1] = nss.read(); //represent byte 2
vals[2] = nss.read(); //represent byte 3
heartRate = 0; // Sets all 8 bits to 0
oxyLevel = 0; // Sets all 8 bits to 0
bitWrite(heartRate, 0, bitRead(vals[1], 0)); // Set bit 0
bitWrite(heartRate, 1, bitRead(vals[1], 1)); // Set bit 1
bitWrite(heartRate, 2, bitRead(vals[1], 2)); // Set bit 2
bitWrite(heartRate, 3, bitRead(vals[1], 3)); // Set bit 3
bitWrite(heartRate, 4, bitRead(vals[1], 4)); // Set bit 4
bitWrite(heartRate, 5, bitRead(vals[1], 5)); // Set bit 5
bitWrite(heartRate, 6, bitRead(vals[1], 6)); // Set bit 6
bitWrite(heartRate, 7, bitRead(vals[0], 0)); // Set bit 7
bitWrite(heartRate, 8, bitRead(vals[0], 1)); // Set bit 8
oxyLevel = vals[2];
}
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = heartRate;
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits
Serial.print("Heart rate: ");
Serial.println(heartRate);
Serial.print("avg: ");
Serial.println(average);
delay(1); // delay in between reads for stability
But the set of code appears 3 times in the loop and it looks like an inefficient way to do it. How to reduce that? or Am I using millis() wrong?
fame3096:
Now, this works just like a delay.
That is because you are using WHILE. If you look at my demo you will see that it uses IF.
Getting your head around the use of millis() can take a little effort, but it is a very fundamental concept for Arduino programming.
Think of the way that you use the clock on the wall in your kitchen. When something starts you save the value of millis() (make a note of the time on the clock) and at regular intervals you compare the latest value of millis() (the current time on your clock) with the value you saved. If the right amount of time has passed you know to take the chicken from the oven.
...R
Thanks for the reply. I still haven't figured it out.
What I am trying to do is that "if" the heartrate goes up, I want a PWM LED to be on for a 5 seconds and then off for 10 seconds even if the heart rate is above the threshold. All this needs to happen while the data is streaming on the serial monitor. To be honest, I am a novice at arduino. My code doesn't seem to do this. Can you please help me out?
unsigned long currentMillis = millis();
unsigned long previousMillis = 0;
void loop()
{
dataread();//function to display serial data
currentMillis = millis();
if(average>60){
if(currentMillis - previousMillis >= 5000) {
analogWrite(11,200);
// setup clock for next tick
previousMillis = currentMillis;
}
dataread();
if(currentMillis - previousMillis >=10000){
analogWrite(11,0);
previousMillis = currentMillis;
}
dataread();
}
else{
analogWrite(11,0);
}
}
thank you!