Having incrementing problems in Arduino code - arduino

Basically I am reading raw values from an accelerometer (i.e these values change in response to gravity and acceleration).
I have set a range of values for the raw values(i.e from -100 to 100 instead):
x = map(ax, -2048, 2048, -100, 100 );
now im trying to increment "count" x greater than 50:
if (x>50) {
count++;
}
main example code here:
void loop(){
x = map(ax, -2048, 2048, -100, 100 );
if (x>50) {
count++;
}
}
but when I compile the code, x becomes greater than 50 and the count just keeps incrementing and what I want it to do is count 'one by one' only when the value becomes greater than 50 seen as the values change as accelerometer moves?

I think you want to count how many times you measure a value over 50. If you check the condition in every loop() iteration, then you will get how many time (measured in loops) the value is over 50.
You need something like this
boolean checked = false;
void loop(){
x = map(ax, -2048, 2048, -100, 100 );
if (x > 50 && !checked) {
count++;
checked = true;
}
if (x < 50 && checked) {
checked = false;
}
}

Related

Arduino Loop not recognizing break condition?

I currently have a nested for loop system that is writing commands to a motor and reading from the attached encoder. For some reason, the program will not break out of the loop using the conditional. I have used some print statements to debug a little and it clearly recognizes that PWMcount is greater than 76 as it prints as far as I will let it count. Any advice is much appreciated, Thank You!
for(int PWMcount = 58;PWMcount < 76;) { //10-20 RAMP
for (int counter = 1; counter < 4;) {
if (counter != 3) {
finalTime = millis();
float newPos;
newPos = encoder.read();
if (newPos != oldPos) {
deltaTime = (finalTime - initialTime);
deltaPos = (newPos-oldPos);
oldPos = newPos;
initialTime = finalTime;
//Serial.println(deltaPos/deltaTime);
}
counter = counter+1;
delay(100);
// Serial.println(PWMcount);
}
else {
finalTime = millis(); //catches time for beginning of each loop iteration
float newPos;
newPos = encoder.read();
if (newPos != oldPos) { //Checks for encoder movement
deltaTime = (finalTime - initialTime); //calculates deltaT in milliseconds
deltaPos = (newPos-oldPos); //sets change in position from one iteration to the next
oldPos = newPos; //Sets old to new to fail if statement unless movement is detected.
initialTime = finalTime; //sets time at beginning of loop to time of ending last loop in order to correctly calculate deltaT in the next iteration
//Serial.println(deltaPos/deltaTime); //Prints rate of the encoder disk in deg/ms (Confirmed by manually taking data and seeing that 1 Rotation outputs values from 0-360
}
counter = 1;
PWMcount=PWMcount+1;
analogWrite(RPWM_Output, PWMcount); // Increases Motor PWM in accordance to loop
}
Serial.println(PWMcount); // UNCOMMENT TO TROUBLESHOOT PWM
delay(100);
}
}
This for loop never completes:
for (int counter = 1; counter < 4;)
The body of the loop is a single if statement. On the last iteration of the loop, the else branch is taken, and that branch sets the loop variable counter back to 1, so the expression counter < 4 is always true, and so that loop never exits.
Since it never exits, the code never gets to a point where the outer loop conditional is tested, nor where the outer loop would ever branch back to the beginning at all.
One possible way to fix the situation would be to combine the two loop conditions, making it a single loop:
for(int PWMcount = 58, counter = 1; PWMcount < 76;) { //10-20 RAMP
if (counter != 3) {
finalTime = millis();
float newPos;
newPos = encoder.read();
if (newPos != oldPos) {
deltaTime = (finalTime - initialTime);
deltaPos = (newPos-oldPos);
oldPos = newPos;
initialTime = finalTime;
//Serial.println(deltaPos/deltaTime);
}
counter = counter+1;
delay(100);
// Serial.println(PWMcount);
}
else {
finalTime = millis(); //catches time for beginning of each loop iteration
float newPos;
newPos = encoder.read();
if (newPos != oldPos) { //Checks for encoder movement
deltaTime = (finalTime - initialTime); //calculates deltaT in milliseconds
deltaPos = (newPos-oldPos); //sets change in position from one iteration to the next
oldPos = newPos; //Sets old to new to fail if statement unless movement is detected.
initialTime = finalTime; //sets time at beginning of loop to time of ending last loop in order to correctly calculate deltaT in the next iteration
//Serial.println(deltaPos/deltaTime); //Prints rate of the encoder disk in deg/ms (Confirmed by manually taking data and seeing that 1 Rotation outputs values from 0-360
}
counter = 1;
PWMcount=PWMcount+1;
analogWrite(RPWM_Output, PWMcount); // Increases Motor PWM in accordance to loop
Serial.println(PWMcount); // UNCOMMENT TO TROUBLESHOOT PWM
delay(100);
}
}
A couple of notes:
The loop condition does not bother to check the counter value, because the loop body obviates the comparison. The counter variable is always less than 4.
I moved the last two lines of the outer loop into the else branch of the if statement. They never executed in your original code, so maybe you just want to remove them altogether. But if the intent was to execute those two lines each line the inner loop reached its end (i.e. counter is 3), then this change matches that intent.

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);
}
}

How to count peaks multiple times?

I am opening a valve to let fluid flow. The pressure being measured here is with how much pressure the fluid is being pulled into a system. I am trying to measure the average value of only first 10 Pdiff (PMax-PMin). once the average value is calculated, the valve is closed.
And based on this average value, the valve will again open and close for 1 peak, and then for 2 peaks, and for 3 peaks and so on. I am storing the pressure value in an array and comparing the value with its before and after value, I get max and min values.
You increment your peakcounter using ++peakcounter but then immediately set peakcounter=0 in the if block of if(peakcounter==0)
Since you reset your peakcounter, you never get to peakcounter == 2
if ( valstate == false && Pdelta >= average)
{
{
++peakcounter; // keeps the count of how many times the value has gone
above average
}
// Checks for the number of times and then performs action
if (peakcounter == 1) {
digitalWrite(4, HIGH);
startTime = millis();
valstate = true;
peakcounter = 0; //the offending line
}
What you need to do the following (Note: code is not optimized. I don't fully understand what you need, but this should fix the issue you wrote about)
int currentMax = 0;
// your code here....
if ( valstate == false && Pdelta >= average){
++peakcounter;
if(peakcounter > currentMax){
// Checks for the number of times and then performs action
if (peakcounter == 1) {
digitalWrite(4, HIGH);
startTime = millis();
valstate = true;
peakcounter = 0;
currentMax++;
}
//the rest of your peakcount checking code here
}

Using spreadsheet to count consecutive cells

So I want to use Google spreadsheet to find how many times does five consecutive cells have a value greater than a given value in a row,but one cell cant be a part of two set of consecutive cells.For example i want to count the number of times a particular item was bought in a month for consecutive five days but if it was bought for 7 days at a stretch it will only be counted as one whereas if it is multiple of five it will be counted as many multiples of five.
For Ex:If cells 1-5 have a value greater than the given value it should give me a count of 1, but if cells 1-9 also are greater than the given value even then it should give me count of 1 but if 1-10 have a value greater than the given value then it should give me a count of 2.I hope this was clear.
I want to write this code in Google Drive using custom function, I tried writing a code in C.
*
int x; //no. of rows
int y; //no. of columns
int arr[x][y]; //array to store numbers
int count[x];
int i,j,k; //for loops
for(i=0;i<x;i++) //set count to 0 for all rows
count[x]=0;
for(i=0;i<x;i++)
{
for(j=0;j<y;j++)
{
for(k=1;k<=5, j<y;k++, j++)
{
if(!arr[i][j]>0)
{
break;
}
else if(k==5 && arr[i][j]!<1)
{
count[i]++;
j--;
}
}
}
}
//display the count array now to see result.
*
You can do this without writing code. That's kinda the purpose of a spreadsheet.
You have one column, say column A, with the values.
In the next column, start a counter that increments each row if the value in the first column is >= your preset value, and reset the counter if not. The formula would be something like (for cell B2)
=IF(A2>=$E$1,B1+1,0)
In the next column, calculate the multiples of 5. For cell C2:
=IF(MOD(B2,5)=0,C1+1,C1)
Copy those cells down to the bottom of the list in column A, and the last value will be the count of values that exceeded cell $e1 a multiple of 5 consecutive times.
Another way using native Sheets functions:
=ArrayFormula((ROWS(A:A)-LEN(REGEXREPLACE(CONCATENATE(LEFT(A:A>=1)),"TTTTT","")))/5)
and using a custom function:
function countGroups(range, comparisonValue, groupSize) {
var v = comparisonValue || 1; // default to comparing to 1 if not specified
var n = groupSize || 5; // default to groups of 5 if not specified
var count = 0, counter = 0;
for (var i = 0, length = range.length; i < length; i++) {
if (range[i][0] >= v) {
counter++;
if (counter == n) {
counter = 0;
count++;
}
}
else
counter = 0;
}
return count;
}

Get 3 Values from processing to Arduino

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">);

Resources