Code Won't Loop

Hi guys,

So I wrote this Arduino code that is supposed to take an input from the serial port of the form <x,y> and then depending on those variables it will preform some action. However one of my codes <1,1> is supposed to loop until an ultrasonic sensor has a distance value less than 8 and a photoresistor has a value less than 200. I have my program print to these values serial port every time it (theoretically) loops for testing. Unfortunately, whenever I use it it’ll only print once and then won’t take any more readings.

Can anyone tell me the problem and some possible solutions?

Thanks guys.

P.S. Also, just as a note, I omitted all of the other <x,y> combinations except <1,1>, and I ripped off most of the Serial port code from one of the forums about serial ports. You can find the original code here :

//----------------------------------------------
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
int messageFromPC = 0;
int integerFromPC = 0;

boolean newData = false;


//------------------------------------------------

//Setting up the Servo.
#include <Servo.h> 
Servo servo1; 

int activeServoAngle = 90; 
int defaultServoAngle = 1;

int servo1Pin = 9; 


//Setting up the ultrasonic sensors.
const int trig1Pin = 12;
const int echo1Pin = 13;


long duration1;
int distance1;



//Setting up the LED.
int LED1Pin = 3;


//Setting up the light sensors
int photocell1Pin = 0;

int photocell1Reading = 0;


//============

void setup() {
    Serial.begin(9600);
    Serial.println("This demo expects 2 pieces of data - text and an integer ");
    Serial.println("Enter data in this style <1, 12>  ");
    Serial.println();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }

//---------------------------------------------

  servo1.attach(servo1Pin); 
  servo1.write(defaultServoAngle);  
  
  pinMode(LED1Pin, OUTPUT);
  digitalWrite(LED1Pin, LOW);

 
  pinMode(trig1Pin, OUTPUT); 
  pinMode(echo1Pin, INPUT);
}

//============

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 parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    messageFromPC = atoi(strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

}

//============

void showParsedData() {  
    if(messageFromPC == 1) {
      if(integerFromPC == 1) {
        servo1.write(activeServoAngle);
        digitalWrite(LED1Pin, HIGH);
        do{   
          delay(100);   
          // Clears the trigPin
          digitalWrite(trig1Pin, LOW);
          delayMicroseconds(2);

          // Sets the trigPin on HIGH state for 10 micro seconds
          digitalWrite(trig1Pin, HIGH);
          delayMicroseconds(10);
          digitalWrite(trig1Pin, LOW);

          // Reads the echoPin, returns the sound wave travel time in microseconds
          duration1 = pulseIn(echo1Pin, HIGH);

          // Calculating the distance
          distance1 = duration1*0.034/2;

          Serial.print("Distance: ");
          Serial.println(distance1);

          photocell1Reading = analogRead(photocell1Pin);

          Serial.print("Photocell: ");
          Serial.println(photocell1Reading);
          
          }while(distance1 > 8);
            if (photocell1Reading <= 200){
            servo1.write(defaultServoAngle); /*sets the servo back to the starting angle*/
            digitalWrite(LED1Pin, LOW);
      
          }
      }//Ends integerFromPC = 1 code
    }
}

Did you test it one step at a time, or just throw a bunch of code together and hope? What prints and what does not? Have you tried debugging by adding lines to print a message showing the progress of the program? Then you can zero in on where the debugging print stops.

Paul

Hi Paul,

Thanks for the reply.

I just threw a bunch of code at it, but I've tested all the individual pieces and the circuit and serial communication code works.

Wait a minute. I just remembered that the reason that the code didn't loop was because both of the sensor values were 0, and which would end the loop. The weird thing is the values shouldn't have been zero. Any advice on how to fix that? Is it in my code? Like I said the circuit worked fine when I tested it.

You are probably using a breadboard with plug-in wires. Always suspect that first.

Paul

        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0

Did you READ the comments? You never use receivedChars again, so the copy just wastes memory.

Reattaching the servo on every pass through loop() is pointless.

ShowParsedData() is NOT the place to USE the parsed data.

messageFromPC is NOT the appropriate name for a variable who's type is int.

Before you just randomly hack at code, you need to THINK.

@PaulS got there before me. Especially regarding "ShowParsedData() is NOT the place to USE the parsed data."

Also the blocking DO/WHILE is generally not a good idea. Just use IF and allow loop() to do the iteration.

...R

PS ... I don't think making an unnecessary copy of receivedChars[] is a major sin unless you are struggling to minimize SRAM usage.

PS ... I don't think making an unnecessary copy of receivedChars[] is a major sin unless you are struggling to minimize SRAM usage.

It's not a major sin.

But, I think everyone that uses code that someone else wrote has an obligation to at least understand what the code does before they modify it or complain that it doesn't work.

Part of that is asking yourself why the code is doing stuff. If it is necessary that receivedChars remain intact (usually it is not) once the parsing is done, then copying the array, and parsing the copy, is important. If not, then don't copy the data unnecessarily.

I understand why you wrote the code the way that you did. But, I think that everyone should read that comment and understand what it implies - that the copy may not be necessary.

@Paul S

Thanks for the response. I'm a bit of a newbie to serial ports, so where should I use the parsed data? The tutorial I got that code from said nothing about that.

RainBox: The tutorial I got that code from said nothing about that.

Post a link to the tutorial.

...R

@Robin2

It's in the first post hyperlinked to the word "here". Also if I recall correctly you wrote it. I could be wrong about that though.

RainBox: It's in the first post hyperlinked to the word "here". Also if I recall correctly you wrote it.

Yes, I wrote Serial Input Basics. But I did not think that was what you were referring to when you said "so where should I use the parsed data? The tutorial I got that code from said nothing about that"

My tutorial made no attempt to suggest how to use the data - I assumed that the user would integrate my tutorial code with his own code.

One way to tackle this sort of problem is to write a program that does not bother with user input and just does the task using fixed data that you put into two variables when writing the program. When that works you can use my tutorial code to update the values in those variables.

Maybe have a look at Planning and Implementing a Program which has simple user input and actions.

...R