Array?

Hello,
Does the Arduino language cater for arrays?
i'm wanting to use three ultraound sensors with one of my i/o boards; is it possible to do something like this:

digitalWrite([1,2,3], LOW);
delayMicroseconds(2);
digitalWrite([1,2,3], HIGH);
delayMicroseconds(5);
digitalWrite([1,2,3], LOW);

(which is how i'd use an array in SuperCollider)

insead of declaring a variable and doing this:

int ultraSoundSignal = 7; // Ultrasound signal pin

digitalWrite(ultraSoundSignal, LOW);
delayMicroseconds(2);
digitalWrite(ultraSoundSignal, HIGH);
delayMicroseconds(5);
digitalWrite(ultraSoundSignal, LOW); // Holdoff

or is there some other way of using an array or list, or do I have to do the above for each pin I am using?

cheers,
will schrimshaw.

Hello Will,

The Arduino language define digitalWrite function as :

void digitalWrite(int pin, int val)
{
      if (digitalPinToPort(pin) != NOT_A_PIN) {
            // If the pin that support PWM output, we need to turn it off
            // before doing a digital write.

            if (analogOutPinToBit(pin) == 1)
                  timer1PWMAOff();

            if (analogOutPinToBit(pin) == 2)
                  timer1PWMBOff();

            if (analogOutPinToBit(pin) == 3)
                  timer2PWMOff();

            if (val == LOW)
                  cbi(_SFR_IO8(port_to_output[digitalPinToPort(pin)]),
                        digitalPinToBit(pin));
            else
                  sbi(_SFR_IO8(port_to_output[digitalPinToPort(pin)]),
                        digitalPinToBit(pin));
      }
}

So you cannot use an array in place of int type definition of the pin parameter of the digitalWrite function.

But I think you can make your own definition of a new function wich can use an int array as parameter.

Benoît ROUSSEAU.

Hello Will,

To complete response to you :

In article LiquidCrystal - Arduino Reference you can see something interesting for you.

int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};
int Enable = 2;

void LcdCommandWrite(int value) {
 // poll all the pins
 int i = 0;
 for (i=DB[0]; i <= DI; i++) {
   digitalWrite(i,value & 01);
   value >>= 1;
 }
 digitalWrite(Enable,LOW);
 delayMicroseconds(1);
 // send a pulse to enable
 digitalWrite(Enable,HIGH);
 delayMicroseconds(1);  // pause 1 ms according to datasheet
 digitalWrite(Enable,LOW);
 delayMicroseconds(1);  // pause 1 ms according to datasheet
}

In particular, see

int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};

void LcdCommandWrite(int value)

and

// poll all the pins
int i = 0;
for (i=DB[0]; i <= DI; i++) {
digitalWrite(i,value & 01);
value >>= 1;
}

Best regards,
Benoît ROUSSEAU

Hi Benoît,

Thanks for digging that out, I'll give it a shot sometime this week. However....

Only just had time to sit down and start figuring out how I might do this (before reading your message).
I have been doubling up some code that worked with one sensor, the data I am getting back seems to be the combined value of the two sensors wired to digital pins 6 and 7, which I am guessing is something to do with this bit:

serialWrite('A'); // Example identifier for the sensor
printInteger(aultrasoundValue);
printInteger(bultrasoundValue);
serialWrite(10);

I was wondering how I might go about sepparating the streams being received on pins 6 and 7? sending some kind of array of the two values rather than their combined value.

all the code is pasted below incase you have time to take a look, I am sure there will be a million things wrong as I'm rather new to arduino.

cheers.

// Ultrasound Sensors

int aultraSoundSignal = 6; // US 1
int bultraSoundSignal = 7; // US 2
int aval = 0;
int bval = 0;
int aultrasoundValue = 0; //US1 Value
int bultrasoundValue = 0; //US2 Value
int atimecount = 0; // Echo counter
int btimecount = 0;
int ledPin = 13; // LED connected to digital pin 13

void setup() {
  beginSerial(9600);                  // Sets the baud rate to 9600
  pinMode(ledPin, OUTPUT);            // Sets the digital pin as output
}

void loop() {
 atimecount = 0;
 btimecount = 0;
 aval = 0;
 bval = 0;
 pinMode(aultraSoundSignal, OUTPUT); // Switch signalpin to output
 pinMode(bultraSoundSignal, OUTPUT);

/* Send low-high-low pulse to activate the trigger pulse of the sensor
 * -------------------------------------------------------------------
 */

digitalWrite(aultraSoundSignal, LOW); // Send low pulse
digitalWrite(bultraSoundSignal, LOW);
delayMicroseconds(2); // Wait for 2 microsecond
digitalWrite(aultraSoundSignal, HIGH); // Send high pulse
digitalWrite(bultraSoundSignal, HIGH);
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(aultraSoundSignal, LOW); // Holdoff
digitalWrite(bultraSoundSignal, LOW);

/* Listening for echo pulse
 * -------------------------------------------------------------------
 */

pinMode(aultraSoundSignal, INPUT); // Switch signalpin to input
aval = digitalRead(aultraSoundSignal); // Append signal value to val
pinMode(bultraSoundSignal, INPUT); // Switch signalpin to input
bval = digitalRead(bultraSoundSignal);

while(aval == LOW) { // Loop until pin reads a high value
  aval = digitalRead(aultraSoundSignal);
  }

while(bval == LOW) { // Loop until pin reads a high value
  bval = digitalRead(bultraSoundSignal);
    
}

while(aval == HIGH) { // Loop until pin reads a high value
  aval = digitalRead(aultraSoundSignal);
  atimecount = atimecount +1;            // Count echo pulse time
  }
  while(bval == HIGH) { // Loop until pin reads a high value
  bval = digitalRead(bultraSoundSignal);
  btimecount = btimecount +1;            // Count echo pulse time
}

/* Writing out values to the serial port
 * -------------------------------------------------------------------
 */

aultrasoundValue = atimecount; // Append echo pulse time to ultrasoundValue
bultrasoundValue = btimecount;

serialWrite('A'); // Example identifier for the sensor
printInteger(aultrasoundValue);
printInteger(bultrasoundValue);
serialWrite(10);

/* Lite up LED if any value is passed by the echo pulse
 * -------------------------------------------------------------------
 */

if(atimecount+btimecount > 0){
  digitalWrite(ledPin, HIGH);
}

/* Delay of program
 * -------------------------------------------------------------------
 */

delay(100);
}

Good evening Will,

Ok, I think that I start to understand your problem.

It's too late for me to respond ZZzzz ! :slight_smile:

But I have a question: do you have to read the two sensors simultaneously? Some 10's milliseconds between the read of the two sensors could be acceptable for your project?

At the first read,

  • I think that an array doesn't change anything ;
  • your code could have some problems if B sensor take a pulse before the A sensor ;
  • using external interrupt could be a best solution for you ;
  • you can reduce your code and optimize it by replacing :
    int aultraSoundSignal = 6; // US 1
    int bultraSoundSignal = 7; // US 2
    by
    #define aultraSoundSignal 6
    #define bultraSoundSignal 7
    note that there no ; at the end of the line.

I'll take a break tomorow to make a new post about this.

Please excuse my poor english.

Best regards,
Benoît ROUSSEAU

Hi Benoît,
A delay of that length will be no problem at all. I had thought that looping the routine and alternating the active pins might be a way around the problem but it was a little late to start working on that last night.
I'll try a few things out this evening.

cheers,

will schrimshaw.

Hi Will,

The next code was not test or compiled, take care... it's just an example :

unsigned long ASensorDelay;
unsigned long BSensorDelay;

unsigned long readSensor (int sensorpin)
{
      // Setup
      // -------------------------------------------------------------------

      int _register = port_to_input[digital_pin_to_port[sensorpin].port]; // register is a reserve word so _ before
      int bit = digital_pin_to_port[sensorpin].bit;
      int mask = 1 << bit;
      unsigned long pulsewidth = 0;
      
      // Send low-high-low pulse to activate the trigger pulse of the sensor
    // -------------------------------------------------------------------

      pinMode (sensorpin, OUTPUT); // sensorpin to output

      digitalWrite (sensorpin, LOW); // Send low pulse
      delayMicroseconds (2); // Wait for 2 microsecond
      digitalWrite (sensorpin, HIGH); // Send high pulse
      delayMicroseconds (5); // Wait for 5 microseconds
      digitalWrite (sensorpin, LOW); // Holdoff

      // Listening for echo pulse
      // -------------------------------------------------------------------

      pinMode (sensorpin, INPUT); // sensorpin to input

      while ((_SFR_IO8(_register) & mask) == LOW); // wait for the pulse to start

      while ((_SFR_IO8(_register) & mask) == HIGH) // wait for the pulse to stop
            pulsewidth++;

      return pulsewidth * 20UL / 23UL;
}

void loop()
{
      ASensorDelay = readSensor (aultraSoundSignal);
      BSensorDelay = readSensor (bultraSoundSignal);

      // Writing out values to the serial port
      // -------------------------------------------------------------------

      serialWrite('A'); printInteger(ASensorDelay); serialWrite(10);
      serialWrite('B'); printInteger(BSensorDelay); serialWrite(10);

      // Lite up LED if any value is passed by the echo pulse
      // -------------------------------------------------------------------

      if(ASensorDelay + BSensorDelay > 0)
            digitalWrite(ledPin, HIGH);

      // Delay of program
      // -------------------------------------------------------------------

      delay(100);
}

I have made a function to read pulse inspired by pulseIn code in wiring.c file :

/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
 * or LOW, the type of pulse to measure.  Works on pulses from 10 microseconds
 * to 3 minutes in length, but must be called at least N microseconds before
 * the start of the pulse. */
unsigned long pulseIn(int pin, int state)
{
      // cache the port and bit of the pin in order to speed up the
      // pulse width measuring loop and achieve finer resolution.  calling
      // digitalWrite() instead yields much coarser resolution.
      int r = port_to_input[digitalPinToPort(pin)];
      int bit = digitalPinToBit(pin);
      int mask = 1 << bit;
      unsigned long width = 0;

      // compute the desired bit pattern for the port reading (e.g. set or
      // clear the bit corresponding to the pin being read).  the !!state
      // ensures that the function treats any non-zero value of state as HIGH.
      state = (!!state) << bit;

      // wait for the pulse to start
      while ((_SFR_IO8(r) & mask) != state)
            ;
      
      // wait for the pulse to stop
      while ((_SFR_IO8(r) & mask) == state)
            width++;
      
      // convert the reading to microseconds.  the slower the CPU speed, the
      // proportionally fewer iterations of the loop will occur (e.g. a 
      // 4 MHz clock will yield a width that is one-fourth of that read with
      // a 16 MHz clock).  each loop was empirically determined to take
      // approximately 23/20 of a microsecond with a 16 MHz clock.
      return width * (16000000UL / F_CPU) * 20 / 23;
}

Something wrong with my code is that you have to have pulse (LOW->HIGH->LOW) return from each sensor to work. Without a pulse, "while" loops are infinite.

If you are uncertain of sensor pulse return, you have to add a counter to check "overload" and a break to exit each while loop. But, you will have minus precision on pulse width measure.

Best regards,
Benoît ROUSSEAU

Hello will,

Your code seems to be inspired by http://webzone.k3.mah.se/projects/arduino-workshop/projects/arduino_meets_processing/instructions/ultrasound.html. So, it works ! And i'm now certain that you have a return pulse each time a sensor is activated. My code, will be ok.

Tell me if it work.

Benoît ROUSSEAU

yeah, got it from the lovely arduino playground, just trying to get it to work for multiple sensors on one board. haven't quite got there yet though..... i'll let you know when it works.

will.