Arduino custom-made function is not working - arduino

I wrote my own Arduino function in order to measure the heart rate. But when it executes it does not work properly. In order to calculate heart rate, I have to do the following calculation:
heart_Rate = 60000/period;
But I realized that the period value keeps accumulating. As a result of that the heart rate reduces. But when I test this without making function (inside void loop) it's working perfectly.
This is my Arduino code:
int H_val = 0;
void setup() {
Serial.begin(9600);
}
float HeartRate() {
int threshold = 750;
int raw_ecg = 0;
int E_input = 0;
float period = 0;
unsigned long p_time = 0;
unsigned long c_time = 0;
int H_rate;
int oldvalue = 0;
oldvalue = raw_ecg;
raw_ecg = 0;
raw_ecg = analogRead(A0);
if (oldvalue < threshold && raw_ecg >= threshold) {
p_time = c_time;
c_time = millis();
period = c_time - p_time;
}
if (period <= 0) {
int H_rate = 0;
} else {
int H_rate = 60000 / period;
return H_rate;
}
delay(2);
}
void loop() {
H_val = HeartRate();
Serial.println(H_val);
}
How do I prevent the period from accumulating?

Every time you call the function, the local variables get initialized again. In your code this means that
p_time = c_time; //c_time = 0
c_time = millis();
period = c_time - p_time;
Hence, period will increase as millis() is increasing.
If you declare the variables as static, your problem will be solved:
static unsigned long p_time = 0;
static unsigned long c_time = 0;
By doing that, the variables keep existing (and keep their value) between function calls and keep their local scope.
The reason it is working inside the loop is that you never leave the loop and the variables never get re-initialized.
Edit: it's enough to declare c_time as static as you assign it's value to p_time anyway. But there are various ways to shorten the code.

It can be a problem of data type. Changing that variables to float or int may solve the problem.
float H_val;
float HeartRate(){
float H_rate;
return H_rate;
}
void loop(){
H_val = HeartRate();
}

Related

Can I use float to store millis function return value as done in the code?

Can I use float data type to store the return value of millis function as shown on the code here? I saw unsigned int type to do it. But look I'm converting that millis to hour. That's why I'm trying to store in float.
#include<Servo.h>
#include<math.h>
Servo mark1;
float dur = 2.30, del_dur = 0 ;
float sys_strt = (millis()/3600000), curr_tim = (millis()/3600000), del_strt = 0;
float inc_val;
const int relay_on = 8;
//2, output = 9;
void setup()
{
digitalWrite(8, HIGH);
mark1.attach(9);
mark1.write(110);//servo on
Serial.begin(9600);
// pinMode(switch_on, INPUT);
// pinMode(output, OUTPUT);
}
void loop()
{
if(Serial.available() > 0)
{
inc_val = Serial.read();
Serial.print("\n");
if(inc_val == 'D') // D = DURATION
{
delay(2000);
dur = Serial.read();
sys_strt = (millis()/3600000);
//mark1.write(on);
}
else if(inc_val == 'd') // d = delay_duration_for_future_turn_on
{
mark1.write(158);// servo off
delay(2000);
del_dur = Serial.read();
Serial.print("\n");
delay (5000);
dur = (Serial.read() + del_dur);
del_strt = (curr_tim + del_dur);
sys_strt = del_strt;
//curr_tim = (millis()/1000);
}
}
if((millis()/3600000) >= 5)
{digitalWrite( 8, LOW);}
if(((millis()/3600000) - del_strt) >= 0 && ((millis()/3600000) - del_strt) <=10 ) // statement for delay duration process
{
mark1.write(110);// servo on
}
if(((millis()/3600000)-sys_strt) >= dur)
{
mark1.write(158);//servo off
}
}
//int x = ((millis() / 1000) - off_timer_start) / 60;
// if (digitalRead(switch_on) == HIGH)
//{
// off_timer_start = (millis() / 1000);
//digitalWrite(output, HIGH);
//}
//else if (x >= offtime && digitalRead(output == HIGH)) {
//digitalWrite(output, LOW);
//}
//delay(1000);
I was trying to store millis return value in float variable. But not sure whether it'll work or not.
There is no need to use float, millis() return an unsigned long which is a 32-bit integer (i.e. equivalent to uint32_t).
Instead of doing division, which is more computationally intensive and has to be done in the runtime for thing like millis()/3600000, you could use 5*3600000 (which is a constant, and the compiler will optimize it to a constant of 18000000 during the compilation) for representing 5 hours. So instead of doing
if((millis()/3600000) >= 5) // do something
it can be done as:
if((millis() >= 5*3600000) // do something
or even better you could define the constant to make your code more readable as:
unsigned long fiveHour = 5*3600000;
if ((millis() >= fiveHour) // do something
It appears that the Arduino related millis() function returns unsigned long, so you cannot store it with full precision in a float.

How to keep millis() at 0?

I'm making an Arduino reverse stopwatch..but Seems to have a problem with millis() function
Whenever I upload the code on Arduino the millis starts running itself..how can I keep it at 0 until I call the millis. or any alternatives to solve it...
#include "SevSeg.h"
int button1 = 11;
int button2 = 12;
int button3 = 13;
int value = 10;
int timer = 0;
bool n = true;
SevSeg Display;
void setup() {
Serial.begin(9600);
byte numDigits = 2;
byte digitPins[] = {9,8};
byte segmentPins[] = {10,2, 3, 4, 5, 6, 7,1};
bool resistorsOnSegments = true;
bool updateWithDelays = true;
byte hardwareConfig = COMMON_ANODE;
Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
Display.setBrightness(100);
}
void loop() {
Display.setNumber(value, 1);
Display.refreshDisplay();
if (digitalRead(11)==HIGH){
Start(value);
}
}
void Start(int value){
while(n){
unsigned long timerGlobal = millis();
Display.setNumber(value-timerGlobal/1000, 1);
Display.refreshDisplay();
if ((value-timerGlobal/1000) == 0){
n = false;
}
}
}
In arduino UNO
extern volatile unsigned long timer0_millis;
noInterrupts ();
timer0_millis = 0;
interrupts ();
But it makes no sense at all.
Simply remember the previous millis and calculate time passed (by substracting).
This should work
//#include "SevSeg.h"
int button1 = 11;
int button2 = 12;
int button3 = 13;
int value = 10;
int timer = 0;
bool n = true;
//Added
int currentTime = 0;
long int t0 = 0;
long int t1 = 0;
//SevSeg Display;
void setup() {
Serial.begin(9600);
byte numDigits = 2;
byte digitPins[] = {9,8};
byte segmentPins[] = {10,2, 3, 4, 5, 6, 7,1};
bool resistorsOnSegments = true;
bool updateWithDelays = true;
//byte hardwareConfig = COMMON_ANODE;
//Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
//Display.setBrightness(100);
}
void loop() {
//Display.setNumber(value, 1);
// Display.refreshDisplay();
if (digitalRead(11)==HIGH){
Start(value);
}
}
void Start(int value){
t0 = millis();
while(n){
t1 = millis();
if(t1 > (1000+t0)){
//has passed 1 second
currentTime++;
if(value-currentTime == 0){
n = false;
}
}
unsigned long timerGlobal = t1-t0;
//Display.setNumber(value-timerGlobal/1000, 1);
//Display.refreshDisplay();
}
}
Just implement a function that subtract the current millis from the previous millis()
The arduino millis() function is not a function that starts a timer. The millis function is meant to get the elapsed milliseconds since the program started.
Keep in mind that the millis() value will overflow afther:
50 days and 70 minutes. so afther this time the millis() will return 0 again and start over again.
You could implement your own timer using interrupts on the arduino. But like a good programmer always say's if something already exits why make it again? just use the millis() and subtract the current from the previous. But keep in mind of the overflow.

Want the numbers in between two limits with equal time interval

I try to get values in between 10 and 100 so I arrange
int pos;
long previousTime =0;
int increment = 1;
int interval = 10;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
long currentTime = millis();
if(currentTime - previousTime > interval){
previousTime = currentTime;
pos +=increment;
if(pos<= 10 || pos > 100){
increment = -increment;
}
Serial.println(pos);
}
}
But my output showing only 1 and 0.If I reduce lower limit into 0 or 1 then I got values in between those limit values given inside the if statement but not getting proper result when I increase the lower limit.Why?
Ok your problem is simple now that we can see the whole code. Look at position, it starts out at 0. On the first pass through loop it gets increments to 1. Then that if statement checks and 1 is indeed less than 10 so it makes increment -1. Then on the next pass through loop that gets added making pos 0 again and since 0 is less than 10 it reverses increment again. It’s doing exactly what you told it.
Try starting pos out at the 10 and see what happens.
If it's not trivial to you, here a suggestion
int pos=0;
unsigned long previousTime =0;
int increment = 1;
int interval = 10;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
unsigned long currentTime = millis();
if(currentTime - previousTime >= interval){
previousTime = currentTime;
pos += increment;
if(pos <= 10) increment = 1;
if(pos >= 100) increment = -1;
// else leave increment as is ...
Serial.println(pos);
}
}

Arduino Wheel Speed Sensor Detect Direction

I'm trying to develop a wheel counter that determines both rotation rate, and the direction of rotation.
I have two magnetic pickup sensors mounted close together, and two metal chunks on the wheel 180 degrees apart.
Currently I have been able to measure rotation rate and convert this to distance, and the distance shown looks good. Here is the code for that:
volatile byte half_revolutions;
volatile byte half_revolutions_b;
volatile unsigned long last_time_a;
volatile unsigned long last_time_b;
volatile byte dir;
unsigned int rpm;
unsigned int rpm_b;
unsigned long timeold;
unsigned long timeold_b;
unsigned long time_print;
double distance = 0.0;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, RISING);
attachInterrupt(1, rpm_fun_b, RISING);
half_revolutions = 0;
half_revolutions_b = 0;
rpm = 0;
timeold = 0;
timeold_b = 0;
time_print = 0;
dir = 1;
}
void loop()
{
int rpm_guess;
if (half_revolutions >= 2)
{
rpm = 30*1000/(millis() - timeold)*half_revolutions;
timeold = millis();
half_revolutions = 0;
}
else if (millis() - timeold > 1000)
{
rpm = 0;
}
if (half_revolutions_b >= 2)
{
rpm_b = 30*1000/(millis() - timeold_b)*half_revolutions_b;
timeold_b = millis();
half_revolutions_b = 0;
}
else if (millis() - timeold_b > 1000)
{
rpm_b = 0;
}
if (millis() - time_print > 500)
{
rpm_guess = ((int)rpm + (int)rpm_b) / 2.0;
double rad_per_sec = (6.0*3.14159* rpm_guess)/180.0;
double metres_per_sec = rad_per_sec*0.038;
distance += metres_per_sec * 0.5;
Serial.print((int)last_time_b - (int)last_time_a);
Serial.print(",");
Serial.println(distance);
time_print = millis();
}
}
void rpm_fun()
{
half_revolutions++;
last_time_a = micros();
//Each rotation, this interrupt function is run twice
}
void rpm_fun_b()
{
half_revolutions_b++;
last_time_b = micros();
//Each rotation, this interrupt function is run twice
}
I was hoping to use the fact that sensor A should lead sensor B if rotation is clockwise, and vice-versa if anti-clockwise. However my logic doesn't seem to be working properly, Serial.print((int)last_time_b - (int)last_time_a); seems to switch between positive and negative no matter the direction I'm travelling.
I'd really appreciated any help with this.
I would rather do the direction guess in the interrupt handler:
void rpm_fun() {
if (last_time_a > last_time_b) dir = 0;
else dir = 1;
half_revolutions++;
last_time_a = micros();
}
void rpm_fun_b() {
if (last_time_a > last_time_b) dir = 0;
else dir = 1;
half_revolutions_b++;
last_time_b = micros();
}
If you experience "bounces", you could add some "debouncing" code.

Recursive functions - argument value not updating after some value

I have written one recursive function and pointer to integer is passed as an argument. That integer value is incremented in function, but I am facing a strange issue that after some value its value never get updated. Even I am checking the value at that address.
Below is the code:--
computeWait(long long int begin, long long int begin2, long long int w,
int* current, int limit)
{
long long int next = 0, arrival = 0;
long long int next1 = 0, service = 0;
long long int serviceTime = 0;
long long int wait = 0;
static long long int Ta = 0;
static long long int Ts = 0;
static long long int W = 0;
while(*current < limit)
{
next = (16807 * begin) % m;
arrival = -200 * log((double)next/m);
next1 = (16807 * begin2) % m;
service = -100 * log(EDRN((double)next1));
wait = max(0, (w + service - arrival));
Ta = Ta + arrival;
Ts = Ts + service;
W = W + wait;
*current = *current + 1;;
computeWait(next, next1, wait, current, limit);
}
printf("\n\nTotal arrival %Ld Total service %Ld Total wait %Ld\n", Ta/limit, Ts/limit, W/limit);
}
int main(int agrc, char* argv[])
{
int num = 0;
int currentValue = 0; // seed number
int end = 1000000;
computeWait(1, 46831694, 0, &currentValue, end);
}
After 103917, its value doesnot get updated and it gives memory protection failure.
Please let me know where I am doing something wrong as it seems so trivial to fix it.
Thanks,
Neha.
Well, I did not really try to understand the code, but I saw some big numbers and the word recursion.
So I would guess its a stack overflow because your recursion is too deep?

Resources