Trying to operate three ultrasonic distance sensors simultaneously to no avail - only the first sensor works. If I comment out the first sensor, then the second starts working and commenting out the second enables the third sensor. I suspect some kind of syntax issue but cannot figure out. Please help:
distance1 = pulseIn(echoPin1, HIGH)/58.2; //Commenting out this line enables "distance 2"
distance2 = pulseIn(echoPin2, HIGH)/58.2; //Commenting out this and the previous lines enables "3"
distance3 = pulseIn(echoPin3, HIGH)/58.2;
Serial.print(distance1);
Serial.println(" cm for monitor 1");
Serial.print(distance2);
Serial.println(" cm for monitor 2");
Serial.print(distance3);
Serial.println(" cm for monitor 3");
delay(250);
}
I am currently using doing 8 Ping sensors single trigger pin
The board is a pro mini clone its a small UNO
This should be the code for the sensors
#define TriggerPin 2 // output pin all trigger pins are linked to.
#define SamplesToAverage 1 // number of ping samples to average together for use
#define DelayBetweenPings 15 // delay after ping data is completely recieved all have reported in and the next trigger pulse in miliseconds (5 seems to be great)
unsigned long Timer, zTimer, xTimer; // Delay timers
volatile unsigned long SampleAge[20];
volatile int PinArray[20] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};; // List of pins that could be used as ping inputs:
unsigned long PingTime[20] ; // Average Ping time array
volatile int ToCompleteCtr; // when interoupted before math we need to c
volatile unsigned long PingTimeX[20]; // Accumulate added sample times to average array
volatile int PingSamplesX[20]; // Accumulate added sample times to average array
volatile unsigned long edgeTime[20]; // time when the pin changed states to high start of timing
volatile uint8_t PCintLast[3]; // the last state that the input pins were in
volatile uint8_t mask[3]; //looking fo pin changes using bianary
int PinMask[3]; // used to make sure all pings are recieved before sending another pulse.
float Measurements[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Times converted to inches or centimeters
byte *MeasurementsB;
bool SerialEvent = false; // Detects serial imput 1
int I2CsendDataGo = 0;
uint8_t dataB[32] ; // Max Wire library buffer size
int c, Pin;
int x = 0;
float inches, cm;
int DegSpread = 0; // 0 displays pin#, 8 will give a count 0~(SensorCount-1) 360 with 8 Sensors will give Degree readings at 45 deg incraments
static int SensorCount = 0; // Counts the number of ping inputs
volatile byte PinList[25]; // Stores a list of Pins for visual output
void setup() {
Serial.begin(115200);
Serial.println("Send 1 for Readable Data, Send 0 For Interger Data");
SensorCount = 0;
pinMode(TriggerPin, OUTPUT);
// enable interrupt for pin...
// Select the pins you want to use for input
// pciSetup(0); // Serial Communication
// pciSetup(1); // Serial Communication
// pciSetup(2);//This is my trigger pin
pciSetup(3);
pciSetup(4);
pciSetup(5);
// pciSetup(6);
// pciSetup(7);
// pciSetup(8);
// pciSetup(9);
// pciSetup(10);
//pciSetup(11);
// pciSetup(12);
// pciSetup(13);
//pciSetup(14); // A0
//pciSetup(15); // A1
// pciSetup(16); // A2
// pciSetup(17); // A3
// pciSetup(18); // A4 i2c Communication
// pciSetup(19); // A5 i2c Communication
}
void loop() {
Timer = millis(); // timing events!
PingIt(); // Manage ping data
if (SerialEvent) SendSerialData();
}
void RadarOut( int Degrees) {
static int x = 0;
static bool xz = true;
static byte Sensor = 0;
int deg = Degrees / SensorCount;
Sensor = 0;
while (Sensor < SensorCount) {
if (Degrees > 0) {
Serial.print((Sensor * deg) );
if (Degrees != SensorCount) {
Serial.print("*");
}
Serial.print("=");
} else {
Serial.print("Pin#");
Serial.print(PinList[Sensor]);
Serial.print("=");
}
Serial.print(Measurements[Sensor]);
Serial.print("cm ");
Sensor++;
}
}
void PingTrigger(int Pin) {
digitalWrite(Pin, LOW);
delayMicroseconds(1);
digitalWrite(Pin, HIGH); // Trigger another pulse
delayMicroseconds(5);
digitalWrite(Pin, LOW);
}
bool AllClear() {
return (!(PinMask[0] & PIND) && !(PinMask[1] & PINB) && !(PinMask[2] & PINC) && !ToCompleteCtr); // all the input pins are LOW
}
void PingIt() {
static int SampleCt = 0;
static bool DelayLatch = true;
if ( AllClear()) { // Wait
if (DelayLatch) {
xTimer = Timer + DelayBetweenPings;
DelayLatch = false;
}
if ((Timer - xTimer) >= 0 ) {
for (int i = 0; i < 20; i++) {
if (SampleCt >= SamplesToAverage) {
byte Sensor = 0;
// Serial.print(i);
if ((PinArray[i] != -1) ) {
//Serial.println("");
// Serial.println(PingTimeX[i]);
if (PingSamplesX[i] > 0) {
// Serial.println(PingSamplesX[i]);
// Serial.println("\t");
// Serial.println(PingTimeX[i]);
PingTime[i] = (unsigned long) (PingTimeX[i] / PingSamplesX[i]); // average
Measurements[Sensor] = (float) (microsecondsToCentimeters(PingTime[i]));
}
PingTimeX[i] = 0;
PingSamplesX[i] = 0;
Sensor++;
}
}
SampleCt = 0;
SampleAge = micros();
}
DelayLatch = true;
SampleCt++;
PingTrigger(TriggerPin); // Send another ping
zTimer = Timer;
}
}
}
float microsecondsToInches(long microseconds)
{
return (float) microseconds / 74 / 2;
}
float microsecondsToCentimeters(long microseconds)
{
return (float)microseconds / 29 / 2;
}
void SendSerialData()
{
SerialEvent = false;
int val = Serial.read() - '0';
while (Serial.available())Serial.read();
if (val == 0) {
DataMessage();
Serial.write(dataB, 30); // respond with message
} else if (val == 1) {
RadarOut( DegSpread);
Serial.println();
}
}
uint8_t DataMessage() {
int x = 0;
for (int i = 0; i < 15; i++ ) {
dataB[x] = (uint8_t)(((uint8_t)Measurements[i]) >> 8);
x++;
dataB[x] = (uint8_t)Measurements[i];
x++;
}
}
// port change Interrupt
ISR(PCINT0_vect) { //this ISR pins 8~13
static uint8_t pin;
static unsigned long cTime;
cTime = micros(); // micros() return a uint32_t
pin = PINB; // get the state of all pins bit 0 = pin 8, bit 1 = pin 9 dtc.
ToCompleteCtr++;
sei(); // re enable other interrupts
CheckTimers(8, 13, 1, pin, cTime);
}
ISR(PCINT1_vect) { //this ISR s A0~A5
static uint8_t pin;
static unsigned long cTime;
cTime = micros(); // micros() return a uint32_t
pin = PINC; // get the state of all pins bit 0 = pin 8, bit 1 = pin 9 dtc.
ToCompleteCtr++;
sei(); // re enable other interrupts
CheckTimers(14, 19, 2, pin, cTime);
}
ISR(PCINT2_vect) { //this ISR pins 0-7
static uint8_t pin;
static unsigned long cTime;
cTime = micros(); // micros() return a uint32_t
pin = PIND; // get the state of all pins bit 0 = pin 8, bit 1 = pin 9 dtc.
ToCompleteCtr++;
sei(); // re enable other interrupts
CheckTimers(0, 7, 0, pin, cTime);
}
void CheckTimers(uint8_t StartPin, uint8_t EndPin, uint8_t group, uint8_t pin, unsigned long cTime )
{
volatile uint16_t dTime;
mask[group] = pin ^ PCintLast[group];
PCintLast[group] = pin; // we memorize the current state of all PINs [D8-D13]
for (uint8_t ii = 0; ii <= (EndPin - StartPin); ii++) {
if (mask[group] >> ii & 1) { // pin has changed
if ((pin >> ii & 1))edgeTime[(ii + StartPin)] = cTime; //Pulse went HIGH store the start time
else { // Pulse Went low calculate the duratoin
dTime = cTime - edgeTime[(ii + StartPin)]; // Calculate the change in time
PingTimeX[(ii + StartPin)] = PingTimeX[(ii + StartPin)] + dTime; // Lets Store any duration up to 65535 micro seconds
PingSamplesX[(ii + StartPin)]++;
}
}
}
ToCompleteCtr--; //when all interupts are complete this will return to zero
}
// Install Pin change interrupt for a pin, can be called multiple times
void pciSetup(byte pin)
{
if (pin <= 7)PinMask[0] = bitWrite(PinMask[0], pin, 1); // PIND for pins 0~7
else if (pin > 13) PinMask[2] = bitWrite(PinMask[2] , pin - 14, 1); // PINC for A0~A5 Starts on Pin 14
else PinMask[1] = bitWrite(PinMask[1] , pin - 8, 1); // PINB for pins 8~13
pinMode(pin, INPUT);// enable interrupt for pin...
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
PinArray[pin] = 1;
PinList[SensorCount] = pin;
SensorCount++;
}
void serialEvent() {
SerialEvent = true;
}
Hi. Thanks for the quick reply. Unfortunately, as much as I tried to figure it out, it is beyond my technical know-how.
Any suggestions why my code does not work? It is straight from the Arduino tutorial and works fine for a single sensor but, as described above, refuses to "see input" from additional sensors.
I need to capture the three sensor input separately to trigger three different actions.
using interrupts at the same time is quite complex but you can make your code work if you re-arrange your code also added a timeout to prevent freezing
#define trigPin2 30
#define echoPin2 31
#define led2 32
#define trigPin1 42
#define echoPin1 43
#define led1 44
#define trigPin3 52
#define echoPin3 53
#define led3 51
void setup() {
Serial.begin (9600);
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(led1, OUTPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(led2, OUTPUT);
pinMode(trigPin3, OUTPUT);
pinMode(echoPin3, INPUT);
pinMode(led3, OUTPUT);
}
void loop() {
int Timeout = 58.2 * 300 // 300 cm max range
long distance1, distance2, distance3;
digitalWrite(trigPin1, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin1, LOW);
distance1 = pulseIn(echoPin1, HIGH,Timeout) / 58.2; //Commenting out this line enables "distance 2"
digitalWrite(trigPin2, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin2, LOW);
distance2 = pulseIn(echoPin2, HIGH.Timeout) / 58.2; //Commenting out this line enables "distance 2"
digitalWrite(trigPin3, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin3, LOW);
distance3 = pulseIn(echoPin3, HIGH,Timeout) / 58.2; //Commenting out this line enables "distance 2"
Serial.print(distance1);
Serial.println(" cm for monitor 1");
Serial.print(distance2);
Serial.println(" cm for monitor 2");
Serial.print(distance3);
Serial.println(" cm for monitor 3");
delay(250);
}
Any suggestions why my code does not work? It is straight from the Arduino tutorial and works fine for a single sensor but, as described above, refuses to "see input" from additional sensors.
pulseIn() is a "blocking" function and nothing else can happen in the program while it is measuring the pulse. By the time it gets around to the second pulse, it is long gone. The triggers and pulse readings need to be sequential.