Hello!
I have a problem sending and receiving values via serial communication as close to real time as possible, I hope someone can help me out.
I am currently working on a project that uses serial communication to send values from Processing to Arduino. I am taking sound input from my headset attached to my laptop and Processing converts them to values that will be send to Arduino to move 4 (later 6) different stepper motors. (Processing is also visualising a movement, that will be translated to the Motors.)
There should be around 5-8 values/ second send back and forth between processing and arduino while arduino uses them to controle the steppermotors. It doesnt seem that much to me or am I wrong?
Im still fairly new, i did a lot of research and testing and this is what i came up with.
I already removed the delays out of the stepper motors step functions using millis() with examples that I adjusted from the following two links
http://forum.arduino.cc/index.php?topic=277692.0
And I used Robins Serial input basic examples from here
http://forum.arduino.cc/index.php?topic=396450.0
To control the received values, I also send them back from the arduino to processing.
The values are send and received in the right order when no motors are included. But when I add them one by one, the values send back from the arduino to processing are getting slower and slower, data gets lost, overwritten and <> sometimes appear though they shoudlnt.
This is my current code
Processing
the whole code is too long due to the visualisation, so i'll show the parts send
void inhaleCalcSendPrint() {
calcMotorValues();
myPort.write("<inhale,"+m1+","+ m2+","+ m3+","+ m4+">");
println("processing inhale: "+m1+","+ m2+","+ m3+","+ m4+",");
output.println("processing inhale: "+m1+","+ m2+","+ m3+","+ m4+",");
}
void exhaleCalcSendPrint() {
calcMotorValues();
myPort.write("<exhale,"+m1+","+ m2+","+ m3+","+ m4+">"); // t8
println("processing exhale: "+m1+","+ m2+","+ m3+","+ m4+",");
output.println("processing exhale: "+m1+","+ m2+","+ m3+","+ m4+",");
}
and read
void serialEvent (Serial myPort) {
if (myPort.available() >0) {
String str = myPort.readString();
if (str != null) {
print(str);
output.print(str);
}
}
}
Arduino
class StepperMotor
{ // Class Member Variables
// These are initialized at startup
int dirPin;
int stepPin;
int motorStep = LOW;
int motorDir = LOW;
long OnTime; // its not millis?
long OffTime;
unsigned long previousMillis = 0; //will store last time motor was updated
unsigned long currentMillis = 0;
int currentSteps = 0;
int stepsForward = 0;
int stepsBackward = 0;
// Constructor - creates a StepperMotor
// and initializes the member variables and state
public:
StepperMotor(int pDirPin, int pStepPin, long on, long off)
{
dirPin = pDirPin;
stepPin = pStepPin;
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
digitalWrite(stepPin, LOW);
OnTime = on;
OffTime = off;
previousMillis = 0;
currentMillis = 0;
}
void turnMotorForward(int steps) {
stepsForward = steps;
digitalWrite(dirPin, HIGH);
while (currentSteps < stepsForward) { // if
currentMillis = millis();
plusStep();
}
currentSteps = 0;
}
void turnMotorBackward(int steps) {
stepsBackward = steps;
digitalWrite(dirPin, LOW);
while (currentSteps < stepsBackward) { // if
currentMillis = millis();
plusStep();
}
currentSteps = 0;
}
void plusStep() {
if ((motorStep == HIGH) && (currentMillis - previousMillis >= OnTime)) {
motorStep = LOW; // Turn it off
previousMillis = currentMillis;
//previousMillis += OnTime; // Remember the time
digitalWrite(stepPin, motorStep);
}
else if ((motorStep == LOW) && (currentMillis - previousMillis >= OffTime)) {
motorStep = HIGH; // turn it on
previousMillis = currentMillis;
//previousMillis += OffTime; // Remember the time
currentSteps++;
digitalWrite(stepPin, motorStep);
}
}
};
StepperMotor stepperMotorA(2, 3, 1, 1);
StepperMotor stepperMotorB(4, 5, 1, 1);
StepperMotor stepperMotorC(6, 7, 1, 1);
StepperMotor stepperMotorD(8, 9, 1, 1);
//StepperMotor stepperMotorE(10, 11, 10, 10);
//StepperMotor stepperMotorF(12, 13, 10, 10);
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
String parts[4];
void setup() {
Serial.begin(19200); // 19200
Serial.println("<Arduino is ready>");
}
void loop() {
recvWithStartEndMarkers();
showNewData();
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
Serial.print(receivedChars);
char* token = strtok(receivedChars, ",");
char* te = token;
token = strtok(0, ",");
int r1 = atoi(token);
token = strtok(0, ",");
int r2 = atoi(token);
token = strtok(0, ",");
int r3 = atoi(token);
token = strtok(0, ",");
int r4 = atoi(token);
String type(te);
if (type == "exhale" ) {
stepperMotorA.turnMotorForward(r1);
stepperMotorB.turnMotorForward(r2);
stepperMotorC.turnMotorForward(r3);
stepperMotorD.turnMotorForward(r4);
} else if (type == "inhale") {
stepperMotorA.turnMotorBackward(-r1);
stepperMotorB.turnMotorBackward(-r2);
stepperMotorC.turnMotorBackward(-r3);
stepperMotorD.turnMotorBackward(-r4);
}
newData = false;
}
}
I believe the problem must be with the way i changed the steps method (turnMotorForward/ turn MotorBackward methods) because when i used those methods with delay shown below and set the delays to 0, the values are send and received in the correct order but of course the motors won't turn with the delays = 0
Code with delay part
void showNewData() {
if (newData == true) {
Serial.print(receivedChars);
char* token = strtok(receivedChars, ",");
char* te = token;
token = strtok(0, ",");
int r1 = atoi(token);
token = strtok(0, ",");
int r2 = atoi(token);
token = strtok(0, ",");
int r3 = atoi(token);
token = strtok(0, ",");
int r4 = atoi(token);
String type(te);
if (type == "exhale" ) {
turnMotorForwards(dirPinA, stepPinA, r1);
turnMotorForwards(dirPinB, stepPinB, r2);
turnMotorForwards(dirPinC, stepPinC, r3);
turnMotorForwards(dirPinD, stepPinD, r4);
} else if (type == "inhale") {
turnMotorBackwards(dirPinA, stepPinA, r1);
turnMotorBackwards(dirPinB, stepPinB, r2);
turnMotorBackwards(dirPinC, stepPinC, r3);
turnMotorBackwards(dirPinD, stepPinD, r4);
}
newData = false;
}
}
void turnMotorBackwards(int dirPin, int stepPin, int steps) {
//Serial.println(steps);
digitalWrite(dirPin, LOW);
for (int i = 0; i > steps; i--) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(highDelay);
digitalWrite(stepPin, LOW);
delay(lowDelay);
}
}
void turnMotorForwards(int dirPin, int stepPin, int steps) {
digitalWrite(dirPin, HIGH); // set direction
for (int i = 0; i < steps; i++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(highDelay);
digitalWrite(stepPin, LOW);
delay(lowDelay);
}
}
Can anyone help me out please?