Reading pins

Hi, I’m using an arduino Nano for a burglar alarm project. I use the analogue pins to get the states of the PIR Sensors.
I have adapted someone else’s code, but I am also taking advantage of the I2c.
To that end I obviously require my code to process the analogue pins A0,A1, A2,A3
Then skip A4&A5 as required for I2c, but I want to continue using A6&A7 for the PIR Sensors.
How can I adapt the code below to do this?

byte i;
  for ( i = 0; i < 4; i++) {
    processSensor( i );
  }/code]

Thanks

Put the pin numbers in an array and iterate through that

const byte sensorPins[] = {A0, A1, A2, A3, A6, A7};

for (int pinIndex = 0; pinIndex < 5; pinIndex++)
{
  processSensor(sensorPins[pinIndex]);
}

Many thanks for the quick reply UKHeliBob.. it makes sense now shown.

Thanks.

I use the analogue pins to get the states of the PIR Sensors.

Why? A PIR sensor detects motion or it doesn’t. There is do level of motion or anything resembling analog data.

Put the pin numbers in an array and iterate through that

Or use two for loops, for the pins below 3 and those above 5. But, since most Arduinos only have one analog pin above 5, a for loop that iterates once would look silly.

PaulS:
Why? A PIR sensor detects motion or it doesn't. There is do level of motion or anything resembling analog data.
Or use two for loops, for the pins below 3 and those above 5. But, since most Arduinos only have one analog pin above 5, a for loop that iterates once would look silly.

The analog pins are used so that I can detect different states of the PIR, such as activated, wire cut, wire shorted, Tamper and so on by using a voltage divider.

Hmm I tried it and it just went crazy! Maybe if I put the whole sketch here it might help.

#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>

const long seconds_start_delay = 5;  // Pause during startup to let PIRs settle down
#define STATE_SHORT        0
#define STATE_NORMAL       1
#define STATE_TAMPER       2
#define STATE_ALARM        3
#define STATE_ALARM_TAMPER 4
#define STATE_CUT          5
#define STATE_UNKNOWN      6
int led = 13;

/* Display config */
#define ENABLE_LCD                 true  // true/false. Enable if you have a Freetronics OLED128 connected
//const long oled_timeout =            20;   // Seconds before screen blanks after last activity

/* Analog readings corresponding to different sensor states */
struct input_ranges {
  int sensor_state;
  const String label;
  int range_bottom;
  int range_optimum;
  int range_top;
};
const input_ranges ranges[] {
  { STATE_SHORT,        "Shorted",         0,    0,  162 },  // 0
  { STATE_NORMAL,       "Normal",        163,  326,  409 },  // 1
  { STATE_TAMPER,       "Tamper",        410,  495,  551 },  // 2
  { STATE_ALARM,        "Alarm",         552,  609,  641 },  // 3
  { STATE_ALARM_TAMPER, "Alarm+Tamper",  642,  675,  848 },  // 4
  { STATE_CUT,          "Cut",           849, 1023, 1023 },  // 5
  { STATE_UNKNOWN,      "Unknown",      1024, 1024, 1024 },  // 6. Range beyond analog in because this is never read
};

/* Connected sensors */
struct sensor {
  const String label;
  byte analog_input;
  byte status_output;
  byte last_state;
};
sensor sensors[] {
  { "A", 0, 4, STATE_UNKNOWN },
  { "B", 1, 5, STATE_UNKNOWN },
  { "C", 2, 6, STATE_UNKNOWN },
  { "D", 3, 7, STATE_UNKNOWN },
};

long lastActivityTime = 0;
char messageBuffer[100];
char topicBuffer[100];
char clientBuffer[20];

/*-----( Declare Constants )-----*/
/*-----( Declare objects )-----*/
// set the LCD address to 0x27 for a 16 chars 2 line display
// A FEW use address 0x3F
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


void setup()
{
   //if (seconds_start_delay > 0)
  {
    Serial.begin(9600);
     if ( ENABLE_LCD == true )
  {
    lcd.begin(16,2);   // initialize the lcd for 16 chars 2 lines, turn on backlight
    // ------- Quick 3 blinks of backlight  -------------
  for(int i = 0; i< 3; i++)
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // finish with backlight on  
 
//-------- Write characters on the display ------------------
// NOTE: Cursor Position: (CHAR, LINE) start at 0  
  lcd.setCursor(0,0); //Start at character 4 on line 0
  lcd.print("Alarm System");
  delay(1000);
  lcd.setCursor(0,1);
  lcd.print("C Brennan V1.0");
  delay(8000);
  lcd.clear();  
 }
    if (seconds_start_delay > 0)
  {
    Serial.print("Pausing ");
    Serial.print( seconds_start_delay );
    Serial.println(" seconds to let sensors settle");

    if ( ENABLE_LCD == true )
    {
      lcd.setCursor(0,0);
      lcd.print(F("Pausing "));
      lcd.setCursor(0,1);
      lcd.print(seconds_start_delay, DEC);
      lcd.print(" Secs to settle");
      //
    }
}

    
    delay(seconds_start_delay * 1000);
     lcd.clear();
}
}
    

void loop()
{
  const byte sensorPins[] = {A0, A1, A2, A3};
  
  for (int pinIndex = 0; pinIndex < 3; pinIndex++) {
    processSensor(sensorPins[pinIndex]);
  }
}



/**
 */
void processSensor( byte sensorId )
{
  int sensorReading = analogRead( sensors[sensorId].analog_input );
//Serial.print(sensorId, DEC);
 //Serial.print(": ");
  //Serial.println(sensorReading, DEC);

  byte sensorState = STATE_UNKNOWN;

  // This should check all entries in the states struct:
  if ( (sensorReading >= ranges[STATE_SHORT].range_bottom) && (sensorReading <= ranges[STATE_SHORT].range_top) ) {
    sensorState = STATE_SHORT;
    digitalWrite (led, HIGH);
  } else if ( (sensorReading >= ranges[STATE_NORMAL].range_bottom) && (sensorReading <= ranges[STATE_NORMAL].range_top) ) {
    sensorState = STATE_NORMAL;
    digitalWrite (led, LOW);
  } else if ( (sensorReading >= ranges[STATE_TAMPER].range_bottom) && (sensorReading <= ranges[STATE_TAMPER].range_top) ) {
    sensorState = STATE_TAMPER;
    digitalWrite (led, HIGH);
  } else if ( (sensorReading >= ranges[STATE_ALARM].range_bottom) && (sensorReading <= ranges[STATE_ALARM].range_top) ) {
    sensorState = STATE_ALARM ;
    digitalWrite (led, HIGH);
  } else if ( (sensorReading >= ranges[STATE_ALARM_TAMPER].range_bottom) && (sensorReading <= ranges[STATE_ALARM_TAMPER].range_top) ) {
    sensorState = STATE_ALARM_TAMPER;
    digitalWrite (led, HIGH);
  } else if ( (sensorReading >= ranges[STATE_CUT].range_bottom) && (sensorReading <= ranges[STATE_CUT].range_top) ) {
    sensorState = STATE_CUT;
    digitalWrite (led, HIGH);
  } else {
    sensorState = STATE_UNKNOWN;
  }

  // Compare to previous value
  if ( sensorState != sensors[sensorId].last_state )
  {
    //lcd.setCursor(0, 1);
    // It changed!
    byte lastSensorState = sensors[sensorId].last_state;
    Serial.print("Sensor ");
    Serial.print(sensorId);
    Serial.print(" changed from ");
    Serial.print(ranges[lastSensorState].label);
    Serial.print(" to ");
    Serial.println(ranges[sensorState].label);
    sensors[sensorId].last_state = sensorState;
    String messageString = sensors[sensorId].label + '-' + String(sensorState);

    Serial.println(messageString);
    lcd.backlight();
    lcd.setCursor(0,0);
    lcd.print("Event: ");
    lcd.setCursor(0,1);
    lcd.print(messageString);
    delay(5000);
    lcd.clear();
    lcd.noBacklight();

    messageString.toCharArray(messageBuffer, messageString.length() + 1);
    String topicString = "sensors";
    topicString.toCharArray(topicBuffer, topicString.length() + 1);
  
  }

}

Cbrenn0823:
The analog pins are used so that I can detect different states of the PIR, such as activated, wire cut, wire shorted, Tamper and so on by using a voltage divider.

How are you going to do that? A lot of those PIR's have a transistor at the output so the signal is only switched high (and pulled high by a resistor).

Btw, it's not working because processSensor() does NOT expect a pin number. It expects a sonsorId which is a number pointing to one of the sensors. So all you needed to do was fill that array with the desired pins.

btw, what evil to use String here....

struct sensor {
  const String label;

septillion:
How are you going to do that? A lot of those PIR's have a transistor at the output so the signal is only switched high (and pulled high by a resistor).

Btw, it's not working because processSensor() does NOT expect a pin number. It expects a sonsorId which is a number pointing to one of the sensors. So all you needed to do was fill that array with the desired pins.

btw, what evil to use String here....

struct sensor {

const String label;

It works fine, as the PIR's use a switch.
I didn't create the code, I have just modified it for me.

Why is it evil BTW? I don't know what is wrong.

When the wife allows I will try fill the array as you have suggested.
Thanks

It works fine, as the PIR's use a switch.

I am not clear what that means in the context of the program. Does the PIR output different voltage levels for different conditions such as the ones you list in reply #4

activated, wire cut, wire shorted, Tamper and so on

I would be interested to see details of the PIR and the circuit being used.

I think this explains better as it's where I got the code.

I'm still lost on this one :frowning:

Here

sensor sensors[] {
  { "A", 0, 4, STATE_UNKNOWN },
  { "B", 1, 5, STATE_UNKNOWN },
  { "C", 2, 6, STATE_UNKNOWN },
  { "D", 3, 7, STATE_UNKNOWN },
};

You make an array with all the sensors with the second field being the analog pin. So if you just don't input 4 and 5 in there you're fine.

And using String (which takes a lot of memory) to just store "A" is pissing away memory. Even more, String is always pissing away memory. Just use c strings (aka char arrays) and you save a lot.