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);
}
}
Related
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.
I am trying to make a radio controlled car which reacts to the frequency of music. The Loop works as it should and it gives me the correct frequency. The function berekenGrootte works too. This gives me the size of the frequency (max frequency - min frequency). But as soon as I want to use the function verdeel() which divides the size of the frequency in 10 to make the car move smoother it does it one or two times and then I don't get any feedback anymore in my serial monitor. Do I use too much Serial.print or do I need to restart the loop after the for loop in the second function?
#include <FreqMeasure.h>
void setup()
{
Serial.begin(57600);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
FreqMeasure.begin();
}
double sum = 0;
int count = 0;
float lowest = 50;
float highest = 0;
float grootte = 50;
float b[9][1];
void loop()
{
if (FreqMeasure.available()) {
// average several reading together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 30) {
float frequency = FreqMeasure.countToFrequency(sum / count);
Serial.println(frequency);
sum = 0;
count = 0;
if (frequency < lowest) {
lowest = frequency;
Serial.print("new lowest: ");
Serial.println(lowest);
berekenGrootte();
}
else if (frequency > highest) {
highest = frequency;
Serial.print("new highest: ");
Serial.println(highest);
berekenGrootte();
}
/*if(frequency > 1000){
digitalWrite(3,HIGH);
delay(1000);
digitalWrite(3,LOW);
}
else{
digitalWrite(5,HIGH);
delay(1000);
digitalWrite(5,LOW);
}*/
}
}
}
void berekenGrootte()
{
grootte = highest - lowest;
Serial.print("new grootte: ");
Serial.println(grootte);
verdeel();
}
void verdeel()
{
float plength = grootte / 10;
b[0][0] = lowest;
b[0][1] = lowest + plength;
Serial.print("low: ");
Serial.println(b[0][0]);
Serial.print("high: ");
Serial.println(b[0][1]);
float startvalue = lowest + plength;
for (int i = 1; i < 10; i++) {
b[i][0] = startvalue;
b[i][1] = startvalue + plength;
startvalue = startvalue + plength;
Serial.print(i);
Serial.print(" low: ");
Serial.println(b[i][0]);
Serial.print(i);
Serial.print(" high: ");
Serial.println(b[i][1]);
}
}
You're overstepping the bounds of your b array.
float b[9][1];
The array is only 9 * 1.
void verdeel()
{
float plength = grootte / 10;
b[0][0] = lowest;
b[0][1] = lowest + plength;
So there is no element b[0][1]. The second number can only go up to 0 since the array is size 1 in that dimension. An array of size 1 is pretty useless as an array.
You have the same problem here in this loop at the end of that function:
for (int i = 1; i < 10; i++) {
b[i][0] = startvalue;
b[i][1] = startvalue + plength;
This for loop allows i to go to 9 which is too large for the array.
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();
}
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.
I have a color tracking program in Processing, which works with a Kinect. When I click somewhere in the picture it saves this color and draws an ellipse around it. I just want to send 3 int values (one for red, green and blue) over myPort.write() to Arduino and save these 3 values in Arduino in 2 variables. My goal is to light a red LED if the red variable is the highest, and the green LED if green is the highest and so on.
I've tried several examples I found whiel googling, but nothing works. I don't know how Arduino should get the correct values in the variables!
EDIT: Here you have my Processing code. I glued it together from several other tutorials until I nearly cried..
import processing.serial.*;
Serial myPort;
import SimpleOpenNI.*;
SimpleOpenNI kinect;
// Frame
PImage currentFrame;
color trackColor;
int r1, g1, b1, r2, g2, b2;
void setup()
{
size(640, 480);
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
kinect = new SimpleOpenNI(this);
kinect.enableRGB();
trackColor = color (255, 0, 0);
smooth ();
currentFrame = createImage (640, 480, RGB);
}
void draw()
{
kinect.update();
currentFrame = kinect.rgbImage ();
image(currentFrame, 0, 0);
currentFrame.loadPixels();
// Before we begin searching, the "world record" for closest color is set to a high number that is easy for the first pixel to beat.
float worldRecord = 500;
// XY coordinate of closest color
int closestX = 0;
int closestY = 0;
// Begin loop to walk through every pixel
for (int x = 0; x < currentFrame.width; x ++ ) {
for (int y = 0; y < currentFrame.height; y ++ ) {
int loc = x + y*currentFrame.width;
// What is current color
color currentColor = currentFrame.pixels[loc];
r1 = (int)red(currentColor);
g1 = (int)green(currentColor);
b1 = (int)blue(currentColor);
r2 = (int)red(trackColor);
g2 = (int)green(trackColor);
b2 = (int)blue(trackColor);
// Using euclidean distance to compare colors
float d = dist(r1, g1, b1, r2, g2, b2); // We are using the dist( ) function to compare the current color with the color we are tracking.
// If current color is more similar to tracked color than
// closest color, save current location and current difference
if (d < worldRecord) {
worldRecord = d;
closestX = x;
closestY = y;
}
}
}
// We only consider the color found if its color distance is less than 10.
// This threshold of 10 is arbitrary and you can adjust this number depending on how accurate you require the tracking to be.
if (worldRecord < 10) {
// Draw a circle at the tracked pixel
fill(trackColor);
strokeWeight(4.0);
stroke(0);
ellipse(closestX, closestY, 30, 30);
}
if (mousePressed == true) {
color c = get(mouseX, mouseY);
//println("r: " + red(c) + " g: " + green(c) + " b: " + blue(c));
// Save color where the mouse is clicked in trackColor variable
int loc = mouseX + mouseY*(currentFrame.width);
trackColor = currentFrame.pixels[loc];
println("red " + r2);
println("green " + g2);
println("blue " + b2);
int colors[] = {r2, g2, b2};
for(int i=0; i < 3; i++) {
myPort.write(colors[i]);
}
}
println("ClosestX " + closestX);
myPort.write(closestX);
}
And my Arduino Code, where I don't know how to get several values.
int val;
int ledPin = 13;
int freq;
int piezoPin = 9;
int redLED = 3;
int greenLED = 5;
int blueLED = 7;
int red, green, blue;
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
digitalWrite(ledPin, LOW);
}
void loop() {
if (Serial.available() > 0)
{ // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if(red > green && red > blue) {
digitalWrite(redLED, HIGH); //light Red LED
}
if(green > red && green > blue) {
digitalWrite(greenLED, HIGH); //light Red LED
}
if(blue > red && blue > green) {
digitalWrite(blueLED, HIGH); //light Red LED
}
//Piezo buzzing higher when X-Position of tracked color is higher.
if (val < 100) {
freq = 50;
}
else if (val < 200) {
freq = 200;
}
else if (val < 300) {
freq = 400;
}
else if (val < 400) {
freq = 600;
}
else if (val < 500) {
freq = 800;
}
else (freq = 1000);
tone(piezoPin, freq);
}
EDIT2: Yes, additionally to lighing the LEDs I also want to have a sound from a piezo buzzer, but that works pretty well, so no questions on that... yet.
Help, please!!
Serial communication to your arduino works with a single byte at a time.
As luck would have it, the three components of a Processing Color are also three bytes.
One for red(0-255)
One for green(0-255)
One for blue(0-255)
Now all we need is a little more info so we can keep them separate.
Because a byte's minimum and maximum values are 0-255, there's no safe character we can use to keep track of the three different bytes, so we need a way to figure out where the info we send begins and ends.
An easy way to do this, is to set up a header and a footer for your messages ; something like :
<color>[byte (red)][byte (green)][byte (blue)]</color>
If we are going to read and decipher messages formatted like this, we are going to need a little buffer that will store the values we receive from Processing, so we can read them back and see if we can match the message format.
So, on the Arduino side, we need this :
String buffer = "";
String messageBegin = "<color>";
String messageEnd = "</color>";
//we read our serial data in the SerialEvent() function
//this is called *after* a loop(), and only if there is serial data in the buffer.
void serialEvent()
{
while(Serial.available())
{
buffer += (char)Serial.read();
}
}
void loop()
{
//now, inside loop, we no longer need to worry about gathering data from serial.
//we do still need to figure out if our message is complete, and then parse it.
//if our buffer contains both the beginning and the end of a message
//in the right order.
int beginIndex = buffer.lastIndexOf(messageBegin);
int endIndex = buffer.lastIndexOf(messageEnd);
if(beginIndex != -1 && endIndex != -1 && beginIndex < endIndex)
{
//we have a complete message!
//our red color starts 7 characters after where the message begins,
//because our "messageBegin" is 7 characters long
string lastMessage = buffer.substring(beginIndex+7);
//this is arguably not the prettiest way to get our byte values back.
//see if you can do better for bonus points!
byte messageAsBytes[80];
lastMessage.getBytes(messageAsBytes, messageAsBytes.length());
//we can now finally reconstruct the value we had from processing!
byte r = (byte)messageAsBytes[0];
byte g = (byte)messageAsBytes[1];
byte b = (byte)messageAsBytes[2];
//if we get a complete message, we can clear our buffer. (don't forget to do this!)
buffer = "";
}
}
On the processing side, all we need to do is make sure our messagebegin and messageend are sent along for the ride :
myPort.write("<color">);
for(int i=0; i < 3; i++) {
myPort.write(colors[i]);
}
myPort.write("</color">);