Ultrasonic Sensor/New Ping Library code

Hello Everyone,

I'm new to the forums and Arduino as a whole and I really cannot work out the problem with this code for the life of me, so, here we go.
I am currently working on an artistic project to use four ultrasonic sensors;

(SRF05 ((http://www.active-robots.com/sensors/object-detection/ultrasonic/srf05-ultrasonic-sensor.html))

which are then attached to four unipolar stepper motors;

(PM25S Unipolar Stepper ((PM25S-048-15 140g-cm Unipolar Stepper))

The aim is that when someone gets closer to the ultrasonic sensor the unipolar stepper starts to step faster and faster. I am using the NewPing library to get the best usage out of my SRF05's. I have successfully coded one SRF05 to one Unipolar Stepper using the 'NewPingExample' as an outline, which works fantastically. Here is the code:

#include <NewPing.h>

#define TRIGGER_PIN  7  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     6  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.


NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
                                     // for your motor   

long previousMillis1 = 0;        // will store last time LED was updated   

long interval1 = 0;           // interval at which to blink (milliseconds)

Stepper myStepper1(stepsPerRevolution, 13,12,11,10); 



void setup() {
  
  myStepper1.step(1);
  
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
  
}

void loop() {
  
   delay(29);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
   unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
   int cm = uS / US_ROUNDTRIP_CM;
   
// here is where you'd put code that needs to be running all the time.

   interval1 = map(cm, 30, 200, 20, 800);
   if(cm >0 && cm <30) interval1 = 20;
   if(cm == 0) interval1 = 800;

   unsigned long currentMillis = millis();
       
 if(currentMillis - previousMillis1 > interval1)
      {
         
            previousMillis1 = currentMillis;  
              
       myStepper1.step(1);
   
      }
      }

(I realise that this coding may not prove to be relevant at all but I hope it shows my logic for coding the four sensors and four steppers, plus being new I'm not sure what the forum posting etiquette is).

But the problem occurs when trying to use multiple SRF05's and Unipolar Steppers. I am using the 'NewPing15Sensors' example as an outline:

#include <NewPing.h>
#include <Stepper.h>

#define SONAR_NUM      2 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

//unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
//unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(22, 23, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(26, 27, MAX_DISTANCE)
  //NewPing(50, 51, MAX_DISTANCE),
  //NewPing(52, 53, MAX_DISTANCE)
};

const int stepsPerRevolution = 200;


int interval1 = 0;
unsigned int previousMillis1 = 0;
unsigned int currentMillis1 = 0;

Stepper myStepper1 (stepsPerRevolution, 30,32,34,36);
//Stepper myStepper2 (stepsPerRevolution, 39,41,43,45);


void setup() {
  Serial.begin(115200);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
    
 myStepper1.step(1);
 //myStepper2.step(1);
 
}

void loop() {
  
  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }
 
  //cm = (int)cm;
  interval1 = map(cm, 30, 300, 20, 800);
  if(cm >0 && cm >30) interval1 = 20;
  if(cm == 0) interval1 = 800;
 
  currentMillis1 = millis();
  
 
  if(currentMillis1 - previousMillis1 > interval1){
    previousMillis1 = currentMillis1;
     myStepper1.step(1);
  }
  

}

void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
  cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    Serial.print(i);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");
  }
  Serial.println();
}

I cannot get my head around why the 'interval1' map functioning will not work. I'm guessing it is to do with the initial unsigned long's and unsigned int's (SONAR_NUM, interval1, previousMillis1 etc) conflicting with the mapping function but my knowledge is limited and I cannot see a solution. Any help, suggestions or just a nudge in the right direction would be greatly appreciated.

Oh, and, mechanically everything seems sound. I have tested both the four sensors working together and the four unipolars working together, just not together, 'together' :stuck_out_tongue:

Many Thanks!

Are you talking about this?

//cm = (int)cm;
  interval1 = map(cm, 30, 300, 20, 800);
  if(cm >0 && cm >30) interval1 = 20;
  if(cm == 0) interval1 = 800;

first you map the range of cm to interval1.
then if cm is greater than 0 and greater than 30 (i.e. greater than 30), set interval1 to 20, even though you just mapped the range for cm>30 to 20-800.

Maybe have a look at constrain().

  for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
    if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
      pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
      if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
      sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
      currentSensor = i;                          // Sensor being accessed.
      cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
      sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
    }
  }

On each pass through loop, see if it is time to ping one of the sensors in the array. If it is, set cm[n] to 0, then ping the sensor AND DISCARD THE RESULT.

  interval1 = map(cm, 30, 300, 20, 800);

Then, try to map an array of values (OK, they are all 0) to a single value, using a function that does not expect an array. That will not work.