Arduino UNO + PCF8574P + 4pcs HC-SR04

0

Estoy intentando conectar 4 sensores ultrasónicos HC-SR04 a Arduino UNO utilizando un chip PCF8574P de NXP. Si hay 4 sensores conectados a los pines Arduino, todo está bien.

El problema aparece cuando trato de enlazarlos a través de PCF8574P. La velocidad de respuesta cae dramáticamente: casi 4 segundos para enviar señales y leer la respuesta de los 4 sensores.

Lo que realmente toma tiempo es pulseIn (). Este es el lugar donde más tiempo me dedico ...

Aquí está el código:

#include <Wire.h>
#include "PCF8574.h"

PCF8574 pcf_us; //Ultrasonic sensors

//The matrix of pin assignments for the ultrasonic sensors (trig (OUTPUT), echo (INPUT))
int usPinMatrix[4][2] = {
  {0, 4}, //0 (pin for trig), 4 (pin for echo)
  {1, 5}, //1 (pin for trig), 5 (pin for echo)
  {2, 6}, //2 (pin for trig), 6 (pin for echo)
  {3, 7}  //3 (pin for trig), 7 (pin for echo)
};

void setup() {
  Serial.begin (9600);
  Serial.println("Initializing device...");

  Wire.begin();

  //PCF8574P I2C address
  /*
    A0 A1 A2 address
    -  -  -  0x20
    +  -  -  0x21
    -  +  -  0x22
    +  +  -  0x23
    -  -  +  0x24
    +  -  +  0x25
    -  +  +  0x26
    +  +  +  0x27
  */
  pcf_us.begin(0x21);

  for (int i = 0; i <= 3; i++){
      pcf_us.pinMode(usPinMatrix[i][0], OUTPUT);
      pcf_us.pinMode(usPinMatrix[i][1], INPUT);
  };

};

void loop() {

  int us_pin, trigPin, echoPin, duration, distance;

  for (int i = 0; i <= 3; i++){

    Serial.print(usPinMatrix[i][0]);
    Serial.print(") ");
    Serial.print("Send sound...   ");

    pcf_us.digitalWrite(usPinMatrix[i][0], HIGH);

    pcf_us.digitalWrite(usPinMatrix[i][0], LOW);

    Serial.print("Switch off...   Reading from ");
    Serial.print(usPinMatrix[i][1]);
    Serial.print("...   ");

    duration = pulseIn(usPinMatrix[i][1], HIGH);
    distance = duration / 2 / 29.1;

    Serial.print("Duration: ");
    Serial.print(duration);
    Serial.print(" s   ");
    Serial.print(distance);
    Serial.println(" cm");

    if (usPinMatrix[i][0] == 3) Serial.println("");

  };

};

Esto es lo que obtengo cuando ejecuto el código:

0) Send sound...   Switch off...   Reading from 4...   [Waiting] Duration: 0 s   0 cm
1) Send sound...   Switch off...   Reading from 5...   [Waiting] Duration: 0 s   0 cm
2) Send sound...   Switch off...   Reading from 6...   [Waiting] Duration: 0 s   0 cm
3) Send sound...   Switch off...   Reading from 7...   [Waiting] Duration: 0 s   0 cm

¿Qué estoy haciendo mal?

    
pregunta llaabbss

1 respuesta

1

Encontré un código de trabajo (probado por mí mismo) para esta tarea exacta. Aquí está: enlace

Aquí está el código:

///////////////////////////////////////////////////////////////////////////////
// Author: RSP @ Embedded System Lab (ESL), KMUTNB, Bangkok/Thailand
// Date: 2015-05-25
// Board: Arduino with ATmega168/328P (5V/16MHz)
// Arduino IDE: version 1.0.6
// Description:
//   This Arduino Sketch demonstrates how to use an Arduino Uno
//   and a PCF8574A chip to interface with multiple ultrasonic distance 
//   sensor modules (up to 4 modules). 
///////////////////////////////////////////////////////////////////////////////

#include <Wire.h> // use the Wire library

// connect address pins: A0=0 (GND), A1=0 (GND), A2=0 (GND)
#define ADDR_BITS (0B000) // A0=0,A1=0,A2=0  
#define I2C_SLAVE_ADDR ((0B0111000) | ADDR_BITS) // 7-bit address

#define MAX_DISTANCE_IN_MM       (4000)   // max. valid value for distance
#define DURATION_TO_DISTANCE(x)  ((17*(x))/100) // usec -> mm.

const int ECHO_PIN = 2; // D2 pin (External Interrupt 0)
const int TRIG_PIN = 4; // D4 pin
const int LED_PIN = 13; // D13 pin

volatile uint32_t tH, tL, pulse_width = 0;
uint16_t dist_mm;       // distance in mm.
char sbuf[32];          // used for sprintf()

void setup() {
   pinMode( LED_PIN, OUTPUT );
   Wire.begin();
   TWBR = 12; // for 400kHz
   writeOutput(0xF0);
   attachInterrupt( 0, eint_isr, CHANGE ); // D2 pin (EINT0)
   Serial.begin( 115200 );
   delay(1000);
}

void writeOutput( byte value ) { // write one byte
  Wire.beginTransmission( I2C_SLAVE_ADDR );
  Wire.write( value ); 
  Wire.endTransmission();
}

byte readInput( void ) { // read one byte
  byte data = 0xff;
  Wire.requestFrom( I2C_SLAVE_ADDR, 1 ); 
  delayMicroseconds(4);
  if ( Wire.available() ) {
     data = Wire.read();
  }
  return data;
}

uint16_t read_ultrasonic_sensor( int pin ) {
  digitalWrite( LED_PIN, HIGH); 
  writeOutput( 0xF0 | (1 << pin) );
  writeOutput( 0xF0 );
  pulse_width = 0;
  while ( pulse_width == 0 ) {}  // wait until pulse_width > 0
  digitalWrite( LED_PIN, LOW ); 
  return DURATION_TO_DISTANCE( pulse_width ); 
}

void loop() {
  for (int i=0; i < 2; i++ ) {
    dist_mm = read_ultrasonic_sensor( i );
    if ( dist_mm > MAX_DISTANCE_IN_MM ) {
      Serial.println( "Out of range." );
    } else {
      sprintf( sbuf, "Sensor %d, %d.%1d cm", i, (dist_mm/10), (dist_mm%10) );
      Serial.println( sbuf );
    }
    delay(5);
  }
  delay( 250 );
}

volatile uint32_t timestamp;

void eint_isr() { // ISR for Ext. Interrupt
  timestamp = micros();  // read the timestamp (in microseconds)
  if ( digitalRead( ECHO_PIN ) == LOW ) { 
    tH = timestamp;
  } else { // HIGH
    tL = timestamp;
    pulse_width = (tL-tH);
  }
}

///////////////////////////////////////////////////////////////////////////////
    
respondido por el llaabbss

Lea otras preguntas en las etiquetas