Problem with Pin Change Interrupts

So the circuit I’m having is just pushbuttons connected to Pin Change capable pins and and at the other end of the pushbuttons are resistors in each ang grounded. .

So here. I’m simulating an intersection. Each intersection has two pushbuttons. 1 button increments the number of supposed vehicles that would arrive at a lane and 1 button that would depart from a lane.
I’m using interrupts for this.

After that. The difference of the departure counter and the arrival counter will be stored on the trafficArray array so this trafficArray[7][4]={
{0,0,0,1},
{0,0,1,0},
{0,1,0,0},
{0,1,0,1},
{1,0,0,0},
{1,0,0,1},
{1,0,1,0}};

will (FOR EXAMPLE) turn to this trafficArray[7][4]={
{0,0,0,5},
{0,0,7,0},
{0,8,0,0},
{0,3,0,2},
{1,0,0,0},
{0,0,0,8},
{11,0,7,0}};

and print the values… but so far it would only print zeroes not matter how many times i push the buttons.

Heres the code.

#include <PinChangeInt.h>
volatile uint8_t sensA[7]={A8,A9,A10,A11,A12,A13,A14};// sensors that would increment during interrupt
volatile uint8_t sensB[7]={A15,50,51,52,53,14};// sensors that would decrement during interrupt
volatile uint8_t queueArrivalRaw[4]={0};
volatile uint8_t queueServiceRaw[4]={0};
double trafficArray[7][4]={
                   {0,0,0,1},
                   {0,0,1,0},
                   {0,1,0,0},
                   {0,1,0,1},
                   {1,0,0,0},
                   {1,0,0,1},
                   {1,0,1,0}};
double queueArrival[4]={0};
double queueService[4]={0};
long previousMillis = 0;      
long T = 90000;   

void increment1() {
    queueArrivalRaw[0]++;}
void decrement1(){
    queueServiceRaw[0]++;}
void increment2() {
    queueArrivalRaw[1]++;}
void decrement2(){
    queueServiceRaw[1]++;}
void increment3() {
    queueArrivalRaw[2]++;}
void decrement3(){
    queueServiceRaw[2]++;}
void increment4() {
    queueArrivalRaw[3]++;}
void decrement4(){
    queueServiceRaw[3]++;}

void setup() {

  for(int i=0; i<7;i++){
    pinMode(sensA[i], INPUT);
    pinMode(sensB[i], INPUT);
    }
  countQueueLength();//initializes the interrupts and counts every interrupt
  sei();//enable global interrupt
  Serial.begin(115200); 
  Serial.println("---------------------------------------");
}

void loop() 
{
  refreshEveryPeriod();//updates the queueService and queueArrival for every T period
  printQueueTraffic();//
    }
    

void  countQueueLength(){
  for(int j=0; j<7;j++){
    if(j<2){
      attachPinChangeInterrupt(sensA[j], increment1, FALLING);
      attachPinChangeInterrupt(sensB[j], decrement1, FALLING);}
    else if(j<4 && j>1){ 
      attachPinChangeInterrupt(sensA[j], increment2, FALLING);
      attachPinChangeInterrupt(sensB[j], decrement2, FALLING);}
    else if(j<6 && j>3){ 
      attachPinChangeInterrupt(sensA[j], increment3, FALLING);
      attachPinChangeInterrupt(sensB[j], decrement3, FALLING);}
    else{
      attachPinChangeInterrupt(sensA[j], increment4, FALLING);
      attachPinChangeInterrupt(sensB[j], decrement4, FALLING);}
  }
}
  
void refreshEveryPeriod(){
    unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > T) {
    previousMillis = currentMillis; 
    for(int i=0;i<4;i++){
      queueArrival[i]=queueArrivalRaw[i];
      queueService[i]=queueServiceRaw[i];
      }
    Serial.println(previousMillis);
  }
}

void printQueueTraffic(){
  Serial.println("Traffic Queue Length");
  for(int i=0;i<7;i++){
    for(int j=0;j<4;j++){
  trafficArray[i][j]=trafficArray[i][j]*(queueArrival[j]-queueService[j]);
  Serial.print(trafficArray[i][j]);
  Serial.print("\t");
    }
  Serial.println();
  }
  delay(1000);
}

So here. I’m simulating an intersection.

Which does NOT require interrupts. Polling the pins is plenty fast.

double trafficArray[7][4]={
                   {0,0,0,1},
                   {0,0,1,0},
                   {0,1,0,0},
                   {0,1,0,1},
                   {1,0,0,0},
                   {1,0,0,1},
                   {1,0,1,0}};

Why are you wasting 4 bytes on these one byte values?

  for(int j=0; j<7;j++){
    if(j<2){

When a for loop isn’t appropriate, don’t use one.

but so far it would only print zeroes not matter how many times i push the buttons.

So, how are the switches wired? Why are you not using the internal pullup resistors and really simple wiring?

Which does NOT require interrupts. Polling the pins is plenty fast.

This code is just part of an entire bigger code. So I would want that while the Arduino is doing other stuff (ie. choosing the largest value in the trafficArray[][] lighting up the traffics lights), it could still count whenever the buttons are pushed.

Why are you wasting 4 bytes on these one byte values?

So I'll just have to do this?

attachPinChangeInterrupt(sensA[0], increment1, FALLING);
attachPinChangeInterrupt(sensA[1], increment1, FALLING);
attachPinChangeInterrupt(sensB[0], decrement1, FALLING);
attachPinChangeInterrupt(sensB[1], decrement1, FALLING);
attachPinChangeInterrupt(sensA[2], increment2, FALLING);
attachPinChangeInterrupt(sensA[3], increment2, FALLING);
attachPinChangeInterrupt(sensB[2], decrement2, FALLING);
attachPinChangeInterrupt(sensB[3], decrement2, FALLING);
attachPinChangeInterrupt(sensA[4], increment3, FALLING);
attachPinChangeInterrupt(sensA[5], increment3, FALLING);
attachPinChangeInterrupt(sensB[4], decrement3, FALLING);
attachPinChangeInterrupt(sensB[5], decrement3, FALLING);
attachPinChangeInterrupt(sensA[6], increment4, FALLING);
attachPinChangeInterrupt(sensB[6], decrement4, FALLING);

So, how are the switches wired? Why are you not using the internal pullup resistors and really simple wiring?

I just wanted to try not using it. Hahaha

So I would want that while the Arduino is doing other stuff (ie. choosing the largest value in the trafficArray[][] lighting up the traffics lights), it could still count whenever the buttons are pushed.

Choosing the largest value in an array takes almost no time. Changing the state of some pins takes almost no time. You will have plenty of time to poll the switches.

So I'll just have to do this?

That makes more sense to me.

I just wanted to try not using it. Hahaha

That didn't answer the question. Poorly wired switches won't trigger interrupts.

If you do use interrupts you will have to do things correctly:

All variables that are written by an ISR should be declared volatile

All accesses in the main code to variables larger than 1 byte need to guarded with noInterrupts() / interrupts() calls so that you never see them mid-update (reading a multibyte variable is not atomic in an 8-bit micro).

Also you will have to tackle debouncing somehow.

Okay got it. I'll just have to poll the pins then.

Choosing the largest value in an array takes almost no time

Sorry. It's not choosing the largest number. Its sorting the array from largest to smallest. Still Achievable?

The system would does this:

  • Polling the pins
  • Count number of times it went LOW
  • Inputting it to another variable in every period
  • This variable will be computed for the queue length
  • The computed value stored in the array
  • Array will be sorted
  • The Sorted array will be computed for the green time and red time
  • Execution of green time and red time
  • Compute the expected queue length and waiting time for the next cycle
  • Repeat sorting array

I would also want to send data on the number of vehicles that departed to another arduino (another intersection) through WIFI bridge connection.

I was worried that the arduino would be too busy that's why I was using interrupts

(reading a multibyte variable is not atomic in an 8-bit micro).

I'm sorry. I don't under stand this part.

gerissemarie: The system would does this:

  • Polling the pins ....

Do you mean that every press of one button increments a number and every press of another button decrements a number (perhaps a different number) and the gaps between button presses are irrelevant. OR Do you want to be able to make several (how many) button presses as a "unit" that would be equivalent to typing (say) 5 on a keyboard. In this case you would need to detect several presses within a pre-determined time period.

Have you looked at the Thread planning and implementing a program? Your list is similar to the list in that Thread. It also illustrates the use of millis() to manage several things without blocking.

...R

Do you mean that every press of one button increments a number and every press of another button decrements a number (perhaps a different number) and the gaps between button presses are irrelevant. OR Do you want to be able to make several (how many) button presses as a "unit" that would be equivalent to typing (say) 5 on a keyboard. In this case you would need to detect several presses within a pre-determined time period.

My bad. The function name, decrement and increment, was from my last code.

With every press of a button increments a number(let say this is the arrival part) and every press of another button increments another number(this will be the departure part). This values will be updated within a pre-determined time period.

I'll look into it :)

gerissemarie: This values will be updated within a pre-determined time period.

In case of confusion the sort of pre-determined period I was think of was 0.5 or 1 second - just long enough for the user to tap the button the maximum number of times.

Another approach might be to allow a max interval (maybe 0.2 secs) between presses. Several presses close together would be added to give (say) 5. But once the user stopped tapping the Arduino would treat that as the number s/he intended to input.

Neither of these is a very reliable way for human input unless there is some live feedback to the user and probably also buttons for accept and cancel.

...R

In case of confusion the sort of pre-determined period I was think of was 0.5 or 1 second - just long enough for the user to tap the button the maximum number of times.

That's what I was thinking of but longer. Haha

Another approach might be to allow a max interval (maybe 0.2 secs) between presses. Several presses close together would be added to give (say) 5. But once the user stopped tapping the Arduino would treat that as the number s/he intended to input.

I'll take note of that.

Neither of these is a very reliable way for human input unless there is some live feedback to the user and probably also buttons for accept and cancel.

Actually, The circuit needs to automatically input without live feedback like the buttons you just mentioned.

Sorry for the late reply. I just saw and read the link. It really helped and madfe more sense. I'll try that.

double trafficArray[7][4]={
                   {0,0,0,1},
                   {0,0,1,0},
                   {0,1,0,0},
                   {0,1,0,1},
                   {1,0,0,0},
                   {1,0,0,1},
                   {1,0,1,0}};

This is going to bite you in the rear later. When you have numbers that are integers, use integer types. Doubles and floats are the devil and should be avoided when possible. You're not trying to count a half a car are you?

The problem is, doubles and floats aren't exact. Sometimes 8 gets stored as 7.9999999. Then when you do some integer math with it you get strange results like 8 / 4 = 1 or something.

gerissemarie: That's what I was thinking of but longer. Haha

How much longer? That may be very important for understanding what is in your mind.

...R