Arduino nano data points missing - arduino

thanks for helping me out with my previous problem.
I am now able to get the data from the arduino to PC using putty with the FSR's attached to a sole and detecting pressures.
The only problem I am facing now is that it seems to be missing instances of Heel strike and Toe Off every now and then.(Image Attached)Plot of data
Blue line represents data from Heel FSR and Red line for Toe FSR
It can be seen from the picture that the arduino is missing a Heel Strike at blue coloured peak No 3 and a toe OFF instant at red peak 5 from the end.
Can any one tell me why this is happening regularly..
I am using arduino nano with baudrate 9600 and 2 FSR's ..On increasing the baudrate above 38400 the loss seems to occur more often
/** Code finds instances of toe off and heel strike using data from FSR's*/
void setup()
{
/*************************************************SERIAL**************************************************/
Serial.begin(9600);
}
/*Variables for FSRS*/
//A0= Toe,A1=Heel
int sum_toe_max = 0,sum_toe_min = 0, sum_heel_max = 0, sum_heel_min = 0 ,toe, heel, temp,diff_toe,diff_heel,data_heel=0, data_toe=0, data_toe2, data_heel2 ;
int heel_max[5] = {0, 0, 0, 0, 0}, toe_max[5] = {0, 0, 0, 0, 0}; /*These arrays holds the top 5 maximas upto the time of calibration*/
int heel_min[5]= {100,100,100,100,100}, toe_min[5]={100,100,100,100,100};/*These arrays holds the top 5 maximas upto the time of calibration*/
float avg_heel_max,avg_heel_min,avg_toe_max,avg_toe_min;/*variables to hold the averages of the valus of max and min arrays*/
float UL=0.80,LL=0.05;/* Setting the Limiters*/
int counter_toe_max = 0, counter_heel_max = 0,counter_toe_min = 0, counter_heel_min = 0;//counter for the number of H and T occured
int cal_limit = 10;/*time for which calibration should go on*/
int timer = 0;/*stores the time elapsed*/
void loop()
{
read_FSR();//Call The FSR function
//read_acc();
}
/*********************************************FSR_TOE***********************************************/
/*Function to read the FSR_TOE data and save to SD*/
void read_FSR()
{
data_toe = analogRead(A0);
data_heel = analogRead(A1);
timer = millis() / 1000;
Serial.print(millis());
Serial.print(" ");
Serial.print(data_toe);
Serial.print(" ");
Serial.println(data_heel);
/*Calibration and finding the maxima uptil cal_limit seconds.*/
if (timer < cal_limit)
{
/*TOE calibration*/
/*To find the top 5 max pressures*/
if (data_toe > toe_max[counter_toe_max])
{
toe_max[counter_toe_max] =data_toe;
counter_toe_max = counter_toe_max + 1;
}
if (counter_toe_max >= 5)
{
counter_toe_max = 0;
}
/*To find the top 5 min pressures*/
if (data_toe < toe_max[counter_toe_min])
{
toe_min[counter_toe_min] = data_toe;
counter_toe_min = counter_toe_min + 1;
}
if (counter_toe_min >= 5)
{
counter_toe_min = 0;
}
/*HEEL FSR calibration*/
/*To find the top 5 max pressures*/
if (data_heel > heel_max[counter_heel_max])
{
heel_max[counter_heel_max] =data_heel;
counter_heel_max = counter_heel_max + 1;
}
if (counter_heel_max >= 5)
{
counter_heel_max = 0;
}
/*To find the top 5 min pressures*/
if (data_heel < heel_min[counter_heel_min])
{
heel_min[counter_heel_min]=data_heel; =
counter_heel_min = counter_heel_min + 1;
}
if (counter_heel_min >= 5)
{
counter_heel_min = 0;
}
}
/*Displaying the maximum and minimum valus array and finding the averages for both the FSR's*/
if (timer == cal_limit && temp == 0)
{
/*Finding sum of the array elements*/
for (int i = 0; i < 5; i++)
{
sum_toe_max = sum_toe_max + toe_max[i];
sum_toe_min = sum_toe_min + toe_min[i];
}
for (int i = 0; i < 5; i++)
{
sum_heel_max = sum_heel_max + heel_max[i];
sum_heel_min = sum_heel_min + heel_min[i];
}
avg_toe_max = sum_toe_max / 5;/*dividing by 5 to get the avg of the 5 values*/
avg_toe_min = sum_toe_min / 5;
avg_heel_max = sum_heel_max / 5;
avg_heel_min = sum_heel_min / 5;
diff_toe = avg_toe_max-avg_toe_min;/*difference between maximas and minimas*/
diff_heel = avg_heel_max-avg_heel_min ;
Serial.println();
Serial.print(F("Avg ToePress max "));
Serial.println(avg_toe_max);
Serial.print(F("Avg ToePress min "));
Serial.println(avg_toe_min);
Serial.print(F("Avg HeelPress max "));
Serial.println(avg_heel_max);
Serial.print(F("Avg HeelPress min "));
Serial.println(avg_heel_min);
Serial.print(F("Diff in avg toe press:"));
Serial.println(diff_toe);
Serial.print(F("Diff in avg heel press:"));
Serial.println(diff_heel);
Serial.print(F("Target HeelPress "));
Serial.println(UL*(avg_heel_max-avg_heel_min));
Serial.print(F("Target ToePress "));
Serial.println(LL*(avg_toe_max-avg_toe_min));
temp = temp + 1;
}
/*Done with calibration( when timer =10s)*/
/*Checking the oncoming data for a condition of Toe Off
Consider it as a toe off if the normalised value of data_toe i.e (data_toe-avg_toe_min)/diff_toe
at the previous instant is greater than LL(Lower Limit) i.e 0.2 times the differnce between the averages of max and min of toe FSR
and the normalised value of data_toe2 at the current instant is lesser than the same*/
if (timer > cal_limit && (data_toe-avg_toe_min)/diff_toe > LL)
{
data_toe2 = analogRead(A0);/*Data toe at the current instant*/
if ((data_toe2-avg_toe_min)/diff_toe < LL)
{
//
Serial.print(timer*1000);
Serial.print(" ");
Serial.print(("f t T "));
Serial.print(data_toe);
Serial.print("Avg min ");
Serial.print(avg_toe_min);
Serial.print("Diff ");
Serial.print(diff_toe);
Serial.println(" TOE");
}
}
/*Checking the oncoming data for a condition of Heel Stike
Consider it as a Heel Strike if the normalised value of data_heel i.e (data_heel2-avg_heel_max)/diff_heel
at the previous instant is lesser than UL(Lower Limit) i.e 0.8 times the differnce between the averages of max and min of heel FSR
and the normalised value of data_heel2 at the current instant is greater than the same*/
if(timer>cal_limit && (data_heel-avg_heel_min)/diff_heel<=UL)
{
data_heel2=analogRead(A1);/*Data heel at the current instant*/
if((data_heel2-avg_heel_min)/diff_heel>=UL)
{
Serial.print(timer*1000);
Serial.print(" ");
Serial.print(("f t H "));
Serial.print(data_heel);
Serial.print(" HEEL");
Serial.println(UL);
Serial.flush();
}
}
}

You define String arr[2][2]={{""}}; but access it later with arr[SD_savr][3]="TO";, arr[SD_savr][4]=Y[0]; and arr[SD_savr][3]="HS";, which is out of bounds and causes undefined behavior, which is the possible cause of your resets.

As you removed SD usage, could you also remove the #include
Does that influence your memory requirements? ( Or even the bad behaviour ? )
Freezing instead of Reset is usually the same cause, just hitting some other address. ;)
I cannot not see any array out of bounds issue with the current code, but that's where I'd double/triple check...
Other questions:
I2C (Wire): you request 14 bytes, but read only 2 of them ? ...
start is a float ? dt should be 0.0, I guess

Related

Arduino loop stops after for loop in called function

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.

Arduino PID DC Motor Position Control

I'm doing a control engineering project, implementing a PID motor position control for automatic antenna tracking system. The system contain a dc motor, absolute encoder, and a motor driver.
Everything work as expected, but one thing. The motor cannot stop at set point value near 0 degree (350 - 359, 0 - 10 degree). The used code:
#include <PID_v1.h>
int RPWM = 5;
int LPWM = 6;
int L_EN = 7;
int R_EN = 8;
boolean pin_state[10];
byte input_pin[] = {1, 2, 3, 4, 9, 10, 11, 12, 13};
int dec_position = 0;
int dc = 0;
double kp = 50, ki = 45, kd = 2;
double input = 0, output = 0, setpoint = 0;
volatile long encoderPos = 0;
PID myPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
void setup() {
pinMode(L_EN, OUTPUT);
pinMode(R_EN, OUTPUT);
pinMode(RPWM, OUTPUT);
pinMode(LPWM, OUTPUT);
for (byte i = 0; i < 9; i++) {
pinMode(input_pin[i], INPUT);
}
TCCR1B = TCCR1B & 0b11111000 | 1;
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(1);
myPID.SetOutputLimits(-255, 255);
digitalWrite(L_EN, HIGH);
digitalWrite(R_EN, HIGH);
}
void loop() {
if (Serial.available() > 0) {
String baca = Serial.readString();
setpoint = baca.toInt();
}
ReadEncoder();
input = dc;
myPID.Compute();
pwmOut(output);
}
void pwmOut(int out) {
if (out > 0) {
analogWrite(RPWM, out);//Sets speed variable via PWM
}
else {
analogWrite(LPWM, abs(out));//Sets speed variable via PWM
}
}
void ReadEncoder() {
// FOR READING ENCODER POSITION, GIVING 0-359 OUTPUT CORRESPOND TO THE ENCODER POSITION
for (byte i = 0; i < 9; i++) {
pin_state[i] = !(digitalRead(input_pin[i]));
}
dec_position = (pin_state[8] * 256) + (pin_state[7] * 128) + (pin_state[6] * 64) + (pin_state[5] * 32) + (pin_state[4] * 16) + (pin_state[3] * 8) + (pin_state[2] * 4) + (pin_state[1] * 2) + pin_state[0];
dc = map(dec_position, 0, 500, 0, 360);
}
When the set point is a value between 10 - 350 the sytem worked well. But when it is not, the motor never stop rotating.
I know the problem is due to a little position overshoot cause the encoder to read a very large error.
For instance, if the setpoint is 0 degree, the motor rotate to reach it. Motor rotation is slowing down as its "now" position approaching 0 degree, but the system is not overshoot free. Therefore, even 1 degree overshoot cause the error value is -359 (set point - now position) and the motor rotate again to reach the desired position.
Need help how to overcome this problem. Sorry for bad english.
Here's the solution
double error;
if (SP>PV) {
if (abs(SP-PV) < abs(-360 + SP - PV)) error = SP - PV;
else error = -360 + SP - PV;
}
else{
if(abs(SP-PV)< abs(360 - PV + SP)) error = SP - PV;
else error = 360 - SP + PV;
}
Instead off simple present value minus the set point for error. The code above return shortest path from present value to set point.
i didn't read your code yet. However, to reach "set point" (SV) you should give for "present value" (PV) an error allowance (EA)
For example: EA = SV - PV.
If EA = (-2,+2)degree then it reach "now position"
And, you should not use degree for angle, you should convert it to position (calculate by pulse)
Hope that concept can help you.

Transition between two Steppers with independently assigned cues

I am going to use two step motors, two easy-drivers, one arduino uno.
Each step motors have gear to rotate, front and back.
First, I'd like to assign multiple rotation cues for each steppers. such as,
int step1cue1 = 329
int step1cue2 = 582
int step1cue3 = 1038
int step1 cue4 = 1790
...
int step2cue1 = 568
int step2cue2 = 1004
int step2cue3 = 1928
int step2cue4 = 3592
...
and each stepper needs minimum 0 and maximum value, such as,
int step1maxcue = 8372
int step2maxcue = 8421
each rotation speed and acceleration need to be set and controllable as well.
I would like to use rotation speed = 0 to make the stepper stopped at the cue.
** Operation
Both steppers start from 0,
First, stepper1 rotates to randomly chosen cue from its step1cues, when it almost reaches to the chosen cue, stepper2 starts to rotate to randomly chosen cue from step2cues.(stepper1 stopped at the cue with speed=0), when step2 almost reaches to its cue, stepper1 starts to rotate to another randomly chosen step1cue (not the current cue).. (stepper2 stops with speed=0).. and repeat this transition between two steppers.
Could you please help me with this code?
I would like to use the code from this,
#include <AccelStepper.h>
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
int pos1 = 3600;
int pos2 = 5678;
void setup()
{
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(2000);
stepper2.setAcceleration(800);
}
void loop()
{
if (stepper1.distanceToGo() == 0)
{
pos1 = -pos1;
stepper1.moveTo(pos1);
}
if (stepper2.distanceToGo() == 0)
{
pos2 = -pos2;
stepper2.moveTo(pos2);
}
stepper1.run();
stepper2.run();
}
I don't know the AccelStepper library, so I can be wrong, but this should do what you requested:
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = { 329, 582, 1038, 1790 ...};
const int step2cues[] = { 568, 1004, 1928, 3592 ...};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 9, 8);
AccelStepper stepper2(1, 7, 6);
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
movingStepper = 1;
}
}
stepper1.run();
stepper2.run();
}
THRESHOLD is the "almost" in your sentence: when it is nearer than this value it will start moving the other motor. Note: the cues should be mode distant one from the other than twice the threshold value, so you won't have mixed conditions (I mean with that threshold the minimum distance from one cue and ANY other should be 40).
And by the way, you don't need to set speed to 0: when the stepper reaches the position it will halt by itself.
EDIT:
The OP asked three more features (print the next cue when chosen, print on serial the current position, set a switch when the motor reaches the cue), so here they are.
First of all I'd separate the second and third feature from the previous code, for clarity reasons. I chose to run that code only when the position changes, but this can easily be changed to
print that code only after a fixed amount of change (e.g. only after a change of 50 or more)
print that code at fixed amount of time (e.g. 0.5 s)
Anyway, here is the code:
int currentPos1 = -1;
int currentPos2 = -1;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if (currentPos1 != stepper1.currentPosition())
{ // Stepper 1 has moved
currentPos1 = stepper1.currentPosition()
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
Serial.print("Motor 1 pos: ");
Serial.println(currentPos1);
}
if (currentPos2 != stepper2.currentPosition())
{ // Stepper 2 has moved
currentPos2 = stepper2.currentPosition()
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
Serial.print("Motor 2 pos: ");
Serial.println(currentPos2);
}
stepper1.run();
stepper2.run();
}
If you choose to modify it in order not to receive frequent motor updates (e.g. by showing the message every half a second) you should move the Stepper X has reached the final position block outside the control, so that it can be executed every iteration:
unsigned long lastShownMessages = 0;
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.print("Next cue for motor 2: ");
Serial.println(nextpos);
movingStepper = 2;
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.print("Next cue for motor 1: ");
Serial.println(nextpos);
movingStepper = 1;
}
}
if ((millis() - lastShownMessages) > 500)
{ // More than 500 ms passed since last update:
Serial.print("Motor 1 pos: ");
Serial.println(stepper1.currentPosition());
Serial.print("Motor 2 pos: ");
Serial.println(stepper2.currentPosition());
lastShownMessages += 500;
}
if (stepper1.distanceToGo() == 0)
{ // Stepper 1 has reached the final position
digitalWrite(switch1, HIGH);
}
else
{
digitalWrite(switch1, LOW);
}
if (stepper2.distanceToGo() == 0)
{ // Stepper 2 has reached the final position
digitalWrite(switch2, HIGH);
}
else
{
digitalWrite(switch2, LOW);
}
stepper1.run();
stepper2.run();
}
PLUS, for a calibration purpose, can I see the rotation value (increment) of the stepper on the Server Monitor ? I can set the speed really low and let it roll, then I could know cue values for the stepcues that I need to set.
#include <AccelStepper.h>
// With matrices it's easier
const int step1cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
const int step2cues[] = {10000 , 20000, 30000 , 40000 , 50000, 60000, 70000, 80000};
// Define two steppers and the pins they will use
AccelStepper stepper1(1, 4, 3);
AccelStepper stepper2(1, 7, 6);
int switch1 = 12;
int switch2 = 13;
byte movingStepper;
// Distance from position when the motor should start
#define THRESHOLD 20
void setup()
{
Serial.begin(9600);
pinMode(switch1, OUTPUT);
pinMode(switch2, OUTPUT);
// A0 should be disconnected. If it is used
// change this to an unused analog pin
randomSeed(analogRead(0));
stepper1.setMaxSpeed(3000);
stepper1.setAcceleration(1000);
stepper2.setMaxSpeed(3000);
stepper2.setAcceleration(1000);
// Make sure that steppers are at zero
stepper1.setCurrentPosition(0);
stepper2.setCurrentPosition(0);
// Pretend that we were moving motor 2
// It is already at position, so first
// loop will move motor 1 to a new position
movingStepper = 2;
}
void loop()
{
if (movingStepper == 1)
{
if (abs(stepper1.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step2cues[random(sizeof(step2cues)/sizeof(int))];
} while (abs(nextpos - stepper2.targetPosition()) < THRESHOLD);
stepper2.moveTo(nextpos);
Serial.println("2");
Serial.println(nextpos);
movingStepper = 2;
if ( nextpos = stepper2.targetPosition() ){
digitalWrite(switch1, HIGH);
}
else {
digitalWrite(switch1, LOW);
}
}
}
else
{
if (abs(stepper2.distanceToGo()) < THRESHOLD)
{
int nextpos;
do
{
nextpos = step1cues[random(sizeof(step1cues)/sizeof(int))];
} while (abs(nextpos - stepper1.targetPosition()) < THRESHOLD);
stepper1.moveTo(nextpos);
Serial.println("1");
Serial.println(nextpos);
movingStepper = 1;
if ( nextpos = stepper1.targetPosition() ){
digitalWrite(switch2, HIGH);
}
else {
digitalWrite(switch2, LOW);
}
}
}
stepper1.run();
stepper2.run();
}

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

Arduino sensor data

Hi I am using an Arduino Flex sensor to control a video game character.
The sensor data is being averaged and remapped to a value of between 0-6.
When the player flexes their bicep it reads the max value (this is perfect) however if the player flexes their arm hard and the sensor reads a max value of 6 for some reason as the player relaxes their arm the declining flex values are being passed into the game engine (instead of going from 6 to zero it drops from 6 to 5 to 4 to 3 to 2 to 1 before reaching zero). Can someone please advise how I should alter my code to make the sensor reading return to 0 instead of declining gradually?
#define NUM_LED 6 //sets the maximum numbers of LEDs
#define MAX_Low 75 //for people with low EMG activity
#define MAX_High 150//for people with high EMG activity
#define Threshold 3 // this sets the light to activate TENS
int reading[10];
int finalReading;
int MAX = 0;
int TENS =3;
int ledState = LOW;
byte litLeds = 0;
byte multiplier = 1;
byte leds[] = {8, 9, 10, 11, 12, 13};
char ch;
char contact;
void setup(){
Serial.begin(9600); //begin serial communications
digitalWrite(TENS, LOW);
for(int i = 0; i < NUM_LED; i++){ //initialize LEDs as outputs
pinMode(leds[i], OUTPUT);
pinMode(TENS, OUTPUT); // Set TENS output to StimPin
}
MAX = MAX_High; //This sets the default to people with high EMG activity.
}
void loop(){
for(int i = 0; i < 10; i++){ //take ten readings in ~0.02 seconds
reading[i] = analogRead(A0) * multiplier;
delay(2);
}
for(int i = 0; i < 10; i++){ //average the ten readings
finalReading += reading[i];
}
finalReading /= 10;
for(int j = 0; j < NUM_LED; j++)
{
digitalWrite(leds[j], LOW);//write all LEDs low and stim pin low
}
finalReading = constrain(finalReading, 0, MAX);
litLeds = map(finalReading, 0, MAX, 0, NUM_LED);
Serial.println(litLeds);
for(int k = 0; k < litLeds; k++){
digitalWrite(leds[k], HIGH); // This turns on the LEDS
}
{
// send data only when you receive data:
if (Serial.available() > 0)
{
ch = Serial.read();
contact=digitalRead(TENS);
if (ch == 'A' && contact==LOW)
{
digitalWrite(TENS, HIGH);
}
else if (ch == 'B' && contact==HIGH)
{
digitalWrite(TENS, LOW);
}
}
}
delay(80);
}
Your sensor doesn't read 6 and immediately 0, you are reading it so fast that you can read the intermediate values. For example: if player opens the arm very fast (250-300 ms, it is fast), you can take up to 3 readings then you can read 3 intermediate values.
You can add more time to the last delay() or use only a value that is the same that the 3 last readings to ensure that there isn't a fast change.

Resources